/**
 @file ctc_usw_interrupt.c

 @author  Copyright (C) 2012 Centec Networks Inc.  All rights reserved.

 @date 2012-10-23

 @version v2.0

 This file define sys functions

*/

/****************************************************************************
*
* Header Files
*
****************************************************************************/
#include "sal.h"
#include "dal.h"
#include "ctc_error.h"
#include "ctc_macro.h"
#include "ctc_interrupt.h"

#include "sys_usw_common.h"
#include "sys_usw_interrupt.h"
#include "sys_usw_interrupt_priv.h"

#include "drv_api.h"
#include "usw/include/drv_chip_ctrl.h"

#include "usw/include/drv_common.h"
/****************************************************************************
*
* Defines and Macros
*
*****************************************************************************/
typedef struct sys_intr_irq_info_s
{
    uint32 irq;
    uint8 irq_idx;
    uint8 prio;
    uint8 group[SYS_USW_MAX_INTR_GROUP] ;
    uint8 group_count;
}
sys_intr_irq_info_t;

#define SYS_INTR_DEFAULT_POLL_INTERVAL 1000
#if (SDB_MEM_MODEL == SDB_MODE)
#define SYS_INTR_INIT_CHECK(lchip)    return CTC_E_NONE
#else
#define SYS_INTR_INIT_CHECK(lchip)           \
    do                                    \
    {                                    \
        if((NULL == p_usw_intr_master[lchip]) || !p_usw_intr_master[lchip]->init_done)  \
        {                                \
            SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " Feature not initialized \n");\
			return CTC_E_NOT_INIT;\
       \
        }                                \
    }while(0)

#endif

#define SYS_INTR_GET_TBL_ID(table_id) (table_id&0xFFFF)
#define SYS_INTR_GET_TBL_INS_ID(table_id) ((table_id>>24)&0xFF)
#define SYS_INTR_GET_TBL_BMP(table_id) ((table_id>>16)&0xFF)
#define SYS_USW_CTC_INTR_MAP_SYS_INTR(intr_type, sub_intr_type, low_intr_type) \
{ \
    p_sys_intr[count].intr = intr_type; \
    p_sys_intr[count].sub_intr = sub_intr_type; \
    p_sys_intr[count++].low_intr = low_intr_type; \
}

extern int32
sys_usw_intr_isr_sup_fatal(uint8 lchip, uint32 intr, void* p_data);

extern int32
sys_usw_intr_isr_sup_normal(uint8 lchip, uint32 intr, void* p_data);

extern int32
sys_usw_intr_isr_pcie(uint8 lchip, uint32 intr, void* p_data);

extern int32
sys_usw_interrupt_reset_hw_cb(uint8 lchip, void* p_user_data);
#if defined E_UNIT && (FEATURE_MODE == 0)
extern int32
sys_usw_eunit_isr_handler(uint8 lchip, uint32 intr, void* p_data);
#endif
extern int32
sys_usw_global_ctl_get(uint8 lchip, ctc_global_control_type_t type, void* value);
extern int32
sys_usw_knet_show_stats(uint8 lchip, uint16 s_index, uint16 end_index);

extern int32
sys_at_interrupt_release_fatal(uint8 lchip, sys_intr_type_t* p_type, uint32 enable);

extern int32
sys_at_interrupt_release_normal(uint8 lchip, sys_intr_type_t* p_type, uint32 enable);

extern bool dal_get_soc_active(uint8 lchip);

/****************************************************************************
*
* Global and Declaration
*
*****************************************************************************/
sys_intr_master_t* p_usw_intr_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};

extern dal_op_t g_dal_op;

/* interrupt register type in D2 */
typedef enum sys_interrupt_reg_type_e
{
    SYS_INTR_REG_TYPE_ABNORMAL = 0,
    SYS_INTR_REG_TYPE_FUNC,
    SYS_INTR_REG_TYPE_MAX
} sys_interrupt_reg_type_t;

/****************************************************************************
*
* Function
*
*****************************************************************************/
extern int32 drv_get_host_type(uint8 lchip);
/****************************************************************************
*
* Function
*
*****************************************************************************/
/**
 @brief mapping from ctc parameter to sys level
*/
int32
sys_usw_interrupt_type_mapping(uint8 lchip, ctc_intr_type_t* p_type, sys_intr_type_t* p_sys_intr, uint8* p_count)
{
    int32 ret = CTC_E_NONE;
    uint8 count = 0;
    CTC_PTR_VALID_CHECK(p_type);
    CTC_PTR_VALID_CHECK(p_sys_intr);
    CTC_PTR_VALID_CHECK(p_count);

    *p_count = 0;
    count = 0;
    switch(p_type->intr)
    {
        case CTC_INTR_CHIP_FATAL:
            SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_CHIP_FATAL, p_type->sub_intr, p_type->low_intr);
            break;
        case CTC_INTR_CHIP_NORMAL:
            SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_CHIP_NORMAL, p_type->sub_intr, p_type->low_intr);
            break;

        /* ptp */
        case CTC_INTR_FUNC_PTP_TS_CAPTURE:
            SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_PTP_TS_CAPTURE_FIFO, INVG, INVG);
            break;
        case CTC_INTR_FUNC_PTP_TOD_PULSE_IN:
            SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_PTP_TOD_PULSE_IN, INVG, INVG);
            break;
        case CTC_INTR_FUNC_PTP_TOD_CODE_IN_RDY:
            SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_PTP_TOD_CODE_IN_RDY, INVG, INVG);
            break;
        case CTC_INTR_FUNC_PTP_SYNC_PULSE_IN:
            SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_PTP_SYNC_PULSE_IN, INVG, INVG);
            break;
        case CTC_INTR_FUNC_PTP_SYNC_CODE_IN_RDY:
            SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_PTP_SYNC_CODE_IN_RDY, INVG, INVG);
            break;

        case CTC_INTR_FUNC_OAM_DEFECT_CACHE:
            SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_OAM_DEFECT_CACHE, INVG, INVG);
            break;

        case CTC_INTR_FUNC_MDIO_CHANGE:
            if (DRV_IS_DUET2(lchip))
            {
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_MDIO_CHANGE_0, INVG, INVG);
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_MDIO_CHANGE_1, INVG, INVG);
            }
            else
            {
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_MDIO_XG_CHANGE_0, INVG, INVG);
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_MDIO_XG_CHANGE_1, INVG, INVG);
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_DP1_MDIO_XG_CHANGE_0, INVG, INVG);
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_DP1_MDIO_XG_CHANGE_1, INVG, INVG);
            }
            break;

        case CTC_INTR_FUNC_EXTRAL_GPIO_CHANGE:
            if (DRV_IS_TSINGMA(lchip))
            {
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_GPIO, INVG, INVG);
            }
            break;

        /* linkagg failover */
        case CTC_INTR_FUNC_LINKAGG_FAILOVER:
            if (!(DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
            {
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_CHAN_LINKDOWN_SCAN, INVG, INVG);
            }
            break;

        /* aps failover */
        case CTC_INTR_FUNC_APS_FAILOVER:
            SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_MET_LINK_SCAN_DONE, INVG, INVG);
            break;

        /* flow stats */
        case CTC_INTR_FUNC_STATS_FIFO:
            SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_STATS_STATUS_ADDR, INVG, INVG);
            break;

        /* DMA */
        case CTC_INTR_DMA_FUNC:
            CTC_MAX_VALUE_CHECK(p_type->sub_intr, MCHIP_CAP(SYS_CAP_DMA_MAX_CHAN_ID));
            SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_DMA, p_type->sub_intr, INVG);
            break;

        case CTC_INTR_FUNC_LINK_CHAGNE:
            CTC_MAX_VALUE_CHECK(p_type->sub_intr, sizeof(uint32)*CTC_INTR_STAT_SIZE-1);
            if (DRV_FROM_TMM(lchip))
            {
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_DP0_MC_MAC0, p_type->sub_intr, INVG);
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_DP0_MC_MAC1, p_type->sub_intr, INVG);
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_DP0_MC_MAC2, p_type->sub_intr, INVG);
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_DP0_MC_MAC3, p_type->sub_intr, INVG);
				if (DRV_IS_TMG(lchip))
				{
					SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_DP0_MC_MAC4, p_type->sub_intr, INVG);
				}
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_DP1_MC_MAC0, p_type->sub_intr, INVG);
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_DP1_MC_MAC1, p_type->sub_intr, INVG);
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_DP1_MC_MAC2, p_type->sub_intr, INVG);
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_DP1_MC_MAC3, p_type->sub_intr, INVG);
				if (DRV_IS_TMG(lchip))
				{
					SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_DP1_MC_MAC4, p_type->sub_intr, INVG);
				}
            }
            else
            {
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_PCS_LINK_31_0, p_type->sub_intr, INVG);
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_PCS_LINK_47_32, p_type->sub_intr, INVG);
            }
            break;
        case CTC_INTR_FUNC_IPFIX_OVERFLOW:
            if (!DRV_IS_DUET2(lchip) && !(DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
            {
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_EPE_IPFIX_USEAGE_OVERFLOW, INVG, INVG);
            }
            SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_IPFIX_USEAGE_OVERFLOW, INVG, INVG);
            break;

        case CTC_INTR_FUNC_STMCTL_STATE:
            if (DRV_FROM_TM(lchip))
            {
                SYS_USW_CTC_INTR_MAP_SYS_INTR(SYS_INTR_FUNC_STMCTL_STATE, INVG, INVG);
            }
            break;

        default:
            ret = CTC_E_NOT_SUPPORT;
            break;
    }
    *p_count = count;

    return ret;
}

#if ((SDK_WORK_PLATFORM == 1) || ((0 == SDK_WORK_PLATFORM) && (1 == SDK_WORK_ENV)))  /* simulation */
int32
_sys_usw_interrupt_model_sim_value(uint8 lchip, uint32 tbl_id, uint32 intr, uint32* bmp, uint32 enable)
{
    uint32 cmd = 0;
    uint32 offset = 0;
    uint32 value_set[CTC_INTR_STAT_SIZE];
    uint32 value_reset[CTC_INTR_STAT_SIZE];
    uint32 intr_vec[CTC_INTR_STAT_SIZE];
    uint8 oper_bmp = 0;
    uint32 ins_id = 0;
    uint8 core_id = 0;

    /*
    if (drv_io_is_asic())
    {
        return 0;
    }
    */

    CTC_BMP_INIT(value_set);
    CTC_BMP_INIT(value_reset);
    ins_id = SYS_INTR_GET_TBL_INS_ID(tbl_id);
    oper_bmp = SYS_INTR_GET_TBL_BMP(tbl_id);
    tbl_id = SYS_INTR_GET_TBL_ID(tbl_id);
    core_id = (oper_bmp & 0x80) ? 1 : 0;

    if (enable)
    {
        /* trigger/set */
    }
    else
    {
        /* clear */

        /* 1. read value */
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, DRV_INS(ins_id, INTR_INDEX_VAL_SET), ((uint64)oper_bmp << 32)|cmd, value_set));
        CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, DRV_INS(ins_id, INTR_INDEX_VAL_RESET), ((uint64)oper_bmp << 32)|cmd, value_reset));

        /* 2. do reset action */
        value_reset[0] &= bmp[0];
        value_reset[1] &= bmp[1];
        value_reset[2] &= bmp[2];

        value_set[0] &= ~value_reset[0];
        value_set[1] &= ~value_reset[1];
        value_set[2] &= ~value_reset[2];

        /* 3. write value */
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, DRV_INS(ins_id, INTR_INDEX_VAL_SET), ((uint64)oper_bmp << 32)|cmd, value_set));
        CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, DRV_INS(ins_id, INTR_INDEX_VAL_RESET), ((uint64)oper_bmp << 32)|cmd, value_set));
    }

    if ((intr < SYS_INTR_MAX) && (MCHIP_INTR(lchip)->interrupt_get_intrvec_offset))
    {
        CTC_BMP_INIT(intr_vec);
        cmd = DRV_IOR(SupCtlIntrVec_t, DRV_ENTRY_FLAG);
        DRV_IOCTL_BMP(lchip, 0, ((uint64)0x40 << 32) | cmd, &intr_vec);
        MCHIP_INTR(lchip)->interrupt_get_intrvec_offset(lchip, (core_id << 24) | intr, &offset);
        CTC_BMP_UNSET(intr_vec, offset);
        cmd = DRV_IOW(SupCtlIntrVec_t, DRV_ENTRY_FLAG);
        DRV_IOCTL_BMP(lchip, 0, ((uint64)0x40 << 32) | cmd, &intr_vec);
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_interrupt_model_sim_mask(uint8 lchip, int32 tbl_id, uint32 bit_offset, uint32 bit_count, uint32 enable)
{
    uint32 cmd = 0;
    uint32 i = 0;
    uint32 mask[CTC_INTR_STAT_SIZE];
    uint32 mask_set[CTC_INTR_STAT_SIZE];
    uint32 mask_reset[CTC_INTR_STAT_SIZE];
    uint8 oper_bmp = 0;
    uint32 ins_id = 0;
    /*
    if (drv_io_is_asic())
    {
        return 0;
    }
    */
    CTC_BMP_INIT(mask);
    CTC_BMP_INIT(mask_set);
    CTC_BMP_INIT(mask_reset);
    ins_id = SYS_INTR_GET_TBL_INS_ID(tbl_id);
    oper_bmp = SYS_INTR_GET_TBL_BMP(tbl_id);
    tbl_id = SYS_INTR_GET_TBL_ID(tbl_id);
    if (enable)
    {
        /* 1. read value */
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, DRV_INS(ins_id, INTR_INDEX_MASK_SET), ((uint64)oper_bmp << 32) | cmd, mask_set));
        CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, DRV_INS(ins_id, INTR_INDEX_MASK_RESET), ((uint64)oper_bmp << 32) | cmd, mask_reset));
        /* 2. do reset action */
        if (CTC_INTR_ALL != bit_offset)
        {
            for (i = 0; i < bit_count; i++)
            {
                CTC_BMP_SET(mask, bit_offset+i);
            }
            mask_reset[0] &= mask[0];
            mask_reset[1] &= mask[1];
            mask_reset[2] &= mask[2];
        }

        mask_set[0] &= ~mask_reset[0];
        mask_set[1] &= ~mask_reset[1];
        mask_set[2] &= ~mask_reset[2];

        /* 3. write value */
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, DRV_INS(ins_id, INTR_INDEX_MASK_SET), ((uint64)oper_bmp << 32) | cmd, mask_set));
        CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, DRV_INS(ins_id, INTR_INDEX_MASK_RESET), ((uint64)oper_bmp << 32) | cmd, mask_set));
    }
    else
    {
        /* 1. read value from set */
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, DRV_INS(ins_id, INTR_INDEX_MASK_SET), ((uint64)oper_bmp << 32) | cmd, mask_set));

        /* 2. sync value to reset */
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, DRV_INS(ins_id, INTR_INDEX_MASK_RESET), ((uint64)oper_bmp << 32) | cmd, mask_set));
    }

    return CTC_E_NONE;
}

#endif /* (SDK_WORK_PLATFORM == 1) */

char*
_sys_usw_interrupt_index_str(uint8 lchip, uint32 index)
{
    switch (index)
    {
    case INTR_INDEX_VAL_SET:
        return "ValueSet";

    case INTR_INDEX_VAL_RESET:
        return "ValueReset";

    case INTR_INDEX_MASK_SET:
        return "MaskSet";

    case INTR_INDEX_MASK_RESET:
        return "MaskReset";

    default:
        return "Invalid";
    }
}

/* In Arctic, table id consists of |ins(8 bits)|oper_bmp(8 bits)|tbl_id(16bits)| */
int32
_sys_usw_interrupt_get_status_common(uint8 lchip, uint32 tbl_id, uint32* p_bmp)
{
    uint32 cmd = 0;
    uint32 value[CTC_INTR_STAT_SIZE] = {0};
    uint32 mask[CTC_INTR_STAT_SIZE] = {0};
    uint8 index = 0;
    uint8 ins_id = 0;
    uint8 oper_bmp = 0;

    ins_id = SYS_INTR_GET_TBL_INS_ID(tbl_id);
    oper_bmp = SYS_INTR_GET_TBL_BMP(tbl_id);
    tbl_id = SYS_INTR_GET_TBL_ID(tbl_id);
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, (INTR_INDEX_VAL_SET + (ins_id <<2)), ((uint64)oper_bmp << 32) | cmd, value));
    
    if (DRV_TABLE_MAX_INDEX(lchip, tbl_id) > (INTR_INDEX_MASK_SET + (ins_id << 2)))
    {
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, (INTR_INDEX_MASK_SET + (ins_id << 2)), ((uint64)oper_bmp << 32) | cmd, mask));
    }

    for(index = 0;index < CTC_INTR_STAT_SIZE;++index)
    {
        p_bmp[index] = value[index] & (~mask[index]);
    }

    return CTC_E_NONE;
}
/* In Arctic, table id consists of |ins(8 bits)|oper_bmp(8 bits)|tbl_id(16bits)| */
STATIC int32
_sys_usw_interrupt_set_en_common(uint8 lchip, uint32 bit_offset, uint32 bit_count, uint32 tbl_id, uint32 enable)
{
    uint32 cmd = 0;
    uint32 i = 0;
    uint32 index = 0;
    uint32 mask[CTC_INTR_STAT_SIZE];
    uint8 oper_bmp = 0;
    uint32 ins_id = 0;

    CTC_BMP_INIT(mask);

    index = (enable) ? INTR_INDEX_MASK_RESET : INTR_INDEX_MASK_SET;
    oper_bmp = SYS_INTR_GET_TBL_BMP(tbl_id);
    ins_id = SYS_INTR_GET_TBL_INS_ID(tbl_id);

#if ((SDK_WORK_PLATFORM == 1) || ((0 == SDK_WORK_PLATFORM) && (1 == SDK_WORK_ENV)))  /* simulation */
    cmd = DRV_IOR(SYS_INTR_GET_TBL_ID(tbl_id), DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, DRV_INS(ins_id,index), ((uint64)oper_bmp << 32) | cmd, mask));
#endif

    for (i = 0; i < bit_count; i++)
    {
        CTC_BMP_SET(mask, bit_offset+i);
    }

    cmd = DRV_IOW(SYS_INTR_GET_TBL_ID(tbl_id), DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, DRV_INS(ins_id,index), ((uint64)oper_bmp << 32) | cmd, mask));

#if ((SDK_WORK_PLATFORM == 1) || ((0 == SDK_WORK_PLATFORM) && (1 == SDK_WORK_ENV)))  /* simulation */
    INTR_SIM_LOCK;
    _sys_usw_interrupt_model_sim_mask(lchip, tbl_id, bit_offset, bit_count, enable);
    INTR_SIM_UNLOCK;
#endif

    return CTC_E_NONE;
}

/* In Arctic, table id consists of |ins(8 bits)|oper_bmp(8 bits)|tbl_id(16bits)| */

STATIC int32
_sys_usw_interrupt_get_en_common(uint8 lchip, uint32 bit_offset, uint32 bit_count, uint32 tbl_id, uint32* p_enable)
{
    uint32 cmd = 0;
    uint32 index = 0;
    uint32 mask[CTC_INTR_STAT_SIZE];
    uint32 ins_id = 0;

    CTC_BMP_INIT(mask);

    *p_enable = 0;
    index = INTR_INDEX_MASK_SET;
    ins_id = SYS_INTR_GET_TBL_INS_ID(tbl_id);
    cmd = DRV_IOR(SYS_INTR_GET_TBL_ID(tbl_id), DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, DRV_INS(ins_id, index), cmd, mask));

    *p_enable = (CTC_BMP_ISSET(mask, bit_offset)) ? FALSE : TRUE;
    
    return CTC_E_NONE;
}


int32
_sys_usw_interrupt_clear_status_normal(uint8 lchip, sys_intr_type_t* p_type, uint32* p_bmp)
{
    uint32 tbl_id = 0;
    uint32 cmd = 0;
    uint16 intr_base = 0;
    uint16 bit_offset = 0;
    uint8 oper_bmp = 0;

    if(p_type->sub_intr != INVG)
    {
        tbl_id = p_usw_intr_master[lchip]->p_intr_sub_abnormal[p_type->intr].p_array[p_type->sub_intr];
        if (p_type->low_intr != INVG && tbl_id != 0) /*only clear low level intr status*/
        {
            if (p_type->low_intr < p_usw_intr_master[lchip]->p_intr_low_normal[p_type->sub_intr].array_size)
            {
                tbl_id = p_usw_intr_master[lchip]->p_intr_low_normal[p_type->sub_intr].p_array[p_type->low_intr];                
            }

            if (p_type->lvl4_intr != INVG)
            {
                intr_base = p_usw_intr_master[lchip]->normal_sub_base ? p_usw_intr_master[lchip]->normal_sub_base[p_type->sub_intr] : 0;
                tbl_id = p_usw_intr_master[lchip]->p_intr_normal_end_tbl[p_type->low_intr + intr_base].p_array[p_type->lvl4_intr];
            }
        }
    }
    else
    {
        /*clear sup level intr status*/
        if (MCHIP_INTR(lchip)->interrupt_get_sup_info)
        {
            MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, p_type->intr, &tbl_id, &bit_offset, NULL);
        }
        /* as all sup-level intr table(MapIntrLogFatalLocl & MapIntrLogNormalLocl) are core level */
    }

    /* for arctic, MapIntrLogNormalLocal/InterruptLogMacNormal/InterruptLogRlmDpNormal is log register, no need clear */
    if (tbl_id == 0 || ((tbl_id & 0xffff) == MapIntrLogNormalLocal_t) || ((tbl_id & 0xffff) == InterruptLogMacNormal_t) || ((tbl_id & 0xffff) == InterruptLogRlmDpNormal_t))
    {
        return CTC_E_NONE;
    }
    
    oper_bmp = ((tbl_id >> 16) & 0x3F) | (p_type->core_id ? 0x80 : 0x40);
    tbl_id = (oper_bmp << 16) | (tbl_id & 0xFF00FFFF);
                         
    cmd = DRV_IOW(SYS_INTR_GET_TBL_ID(tbl_id), DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, (INTR_INDEX_VAL_RESET + (SYS_INTR_GET_TBL_INS_ID(tbl_id)<<2)), 
            ((uint64)oper_bmp << 32) | cmd, p_bmp));

#if ((SDK_WORK_PLATFORM == 1) || ((0 == SDK_WORK_PLATFORM) && (1 == SDK_WORK_ENV)))  /* simulation */
    _sys_usw_interrupt_model_sim_value(lchip, tbl_id, p_type->intr, p_bmp, FALSE);
#endif    

    return CTC_E_NONE;
}


int32
_sys_usw_interrupt_clear_status_fatal(uint8 lchip, sys_intr_type_t* p_type, uint32* p_bmp)
{
    uint32 tbl_id = 0;
    uint32 cmd = 0;
    uint16 intr_base = 0;
    uint16 bit_offset = 0;
    uint8 oper_bmp = 0;

    if(p_type->sub_intr != INVG)
    {
        tbl_id = p_usw_intr_master[lchip]->p_intr_sub_abnormal[p_type->intr].p_array[p_type->sub_intr];
        if (p_type->low_intr != INVG && tbl_id != 0) /*only clear low level intr status*/
        {
            if (p_type->low_intr < p_usw_intr_master[lchip]->p_intr_low_fatal[p_type->sub_intr].array_size)
            {
                tbl_id = p_usw_intr_master[lchip]->p_intr_low_fatal[p_type->sub_intr].p_array[p_type->low_intr];
            }

            if (p_type->lvl4_intr != INVG)
            {
                intr_base = p_usw_intr_master[lchip]->fatal_sub_base ? p_usw_intr_master[lchip]->fatal_sub_base[p_type->sub_intr] : 0;
                tbl_id = p_usw_intr_master[lchip]->p_intr_fatal_end_tbl[p_type->low_intr + intr_base].p_array[p_type->lvl4_intr];
            }
        }
    }
    else
    {
        /*clear sup level intr status*/
        if (MCHIP_INTR(lchip)->interrupt_get_sup_info)
        {
            MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, p_type->intr, &tbl_id, &bit_offset, NULL);
        }
        /* as all sup-level intr table(MapIntrLogFatalLocl & MapIntrLogNormalLocl) are core level */
    }

    /* for arctic, MapIntrLogFatalLocal/InterruptLogRlmDpFatal is log register, no need clear */
    if (tbl_id == 0 || ((tbl_id & 0xffff) == MapIntrLogFatalLocal_t) || ((tbl_id & 0xffff) == InterruptLogRlmDpFatal_t))
    {
        return CTC_E_NONE;
    }
    
    oper_bmp = ((tbl_id >> 16) & 0x3F) | (p_type->core_id ? 0x80 : 0x40);
    tbl_id = (oper_bmp << 16) | (tbl_id & 0xFF00FFFF);
                         
    cmd = DRV_IOW(SYS_INTR_GET_TBL_ID(tbl_id), DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, (INTR_INDEX_VAL_RESET + (SYS_INTR_GET_TBL_INS_ID(tbl_id)<<2)), 
            ((uint64)oper_bmp << 32) | cmd, p_bmp));

#if ((SDK_WORK_PLATFORM == 1) || ((0 == SDK_WORK_PLATFORM) && (1 == SDK_WORK_ENV)))  /* simulation */
    _sys_usw_interrupt_model_sim_value(lchip, tbl_id, p_type->intr, p_bmp, FALSE);
#endif    

    return CTC_E_NONE;
}

int32
_sys_usw_interrupt_get_status_normal(uint8 lchip, sys_intr_type_t* p_type, uint32* p_bmp)
{
    uint32 tbl_id = 0;
    uint16 bit_offset = 0;
    uint16 intr_base = 0;
    uint8 oper_bmp = 0;

    if(p_type->sub_intr != INVG)
    {
        tbl_id = p_usw_intr_master[lchip]->p_intr_sub_abnormal[p_type->intr].p_array[p_type->sub_intr];
        if (p_type->low_intr != INVG && tbl_id != 0)
        {
            if (p_type->low_intr < p_usw_intr_master[lchip]->p_intr_low_normal[p_type->sub_intr].array_size)
            {
                tbl_id = p_usw_intr_master[lchip]->p_intr_low_normal[p_type->sub_intr].p_array[p_type->low_intr];
            }
            else
            {
                tbl_id = 0;
            }
            
            if (p_type->lvl4_intr != INVG && tbl_id != 0)
            {
                intr_base = p_usw_intr_master[lchip]->normal_sub_base ? p_usw_intr_master[lchip]->normal_sub_base[p_type->sub_intr] : 0;
                tbl_id = p_usw_intr_master[lchip]->p_intr_normal_end_tbl[p_type->low_intr + intr_base].p_array[p_type->lvl4_intr];
            }
        }
    }
    else
    {
        /* get sup level abnormal intr status */
        if (MCHIP_INTR(lchip)->interrupt_get_sup_info)
        {
            MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, p_type->intr, &tbl_id, &bit_offset, NULL);
        }

        /* as all sup-level intr table are core level */
    }

    if (tbl_id == 0)
    {
        return CTC_E_NONE;
    }

    oper_bmp = ((tbl_id >> 16) & 0x3F) | (p_type->core_id ? 0x80 : 0x40);
    tbl_id = (oper_bmp << 16) | (tbl_id & 0xFF00FFFF);
    CTC_ERROR_RETURN(_sys_usw_interrupt_get_status_common(lchip, tbl_id, p_bmp));
    return CTC_E_NONE;
}

int32
_sys_usw_interrupt_get_status_fatal(uint8 lchip, sys_intr_type_t* p_type, uint32* p_bmp)
{
    uint8 oper_bmp = 0;
    uint16 bit_offset = 0;
    uint16 intr_base = 0;
    uint32 tbl_id = 0;

    if(p_type->sub_intr != INVG)
    {
        tbl_id = p_usw_intr_master[lchip]->p_intr_sub_abnormal[p_type->intr].p_array[p_type->sub_intr];
        if (p_type->low_intr != INVG && tbl_id != 0)
        {
            if (p_type->low_intr < p_usw_intr_master[lchip]->p_intr_low_fatal[p_type->sub_intr].array_size)
            {
                tbl_id = p_usw_intr_master[lchip]->p_intr_low_fatal[p_type->sub_intr].p_array[p_type->low_intr];
            }
            else
            {
                tbl_id = 0;
            }
            
            if (p_type->lvl4_intr != INVG && tbl_id != 0)
            {
                intr_base = p_usw_intr_master[lchip]->fatal_sub_base ? p_usw_intr_master[lchip]->fatal_sub_base[p_type->sub_intr] : 0;
                tbl_id = p_usw_intr_master[lchip]->p_intr_fatal_end_tbl[p_type->low_intr + intr_base].p_array[p_type->lvl4_intr];
            }
        }
    }
    else
    {
        /* get sup level abnormal intr status */
        if (MCHIP_INTR(lchip)->interrupt_get_sup_info)
        {
            MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, p_type->intr, &tbl_id, &bit_offset, NULL);
        }

        /* as all sup-level intr table are core level */
    }

    if (tbl_id == 0)
    {
        return CTC_E_NONE;
    }

    oper_bmp = ((tbl_id >> 16) & 0x3F) | (p_type->core_id ? 0x80 : 0x40);
    tbl_id = (oper_bmp << 16) | (tbl_id & 0xFF00FFFF);
    CTC_ERROR_RETURN(_sys_usw_interrupt_get_status_common(lchip, tbl_id, p_bmp));
    return CTC_E_NONE;
}


STATIC int32
_sys_usw_interrupt_set_en_abnormal(uint8 lchip, sys_intr_type_t* p_type, uint32 enable)
{
    uint8 oper_bmp = 0;
    uint16 bit_offset = 0;
    uint32 tbl_id = 0;
    uint32 sub_tbl_id = 0;

    if (p_type->sub_intr != INVG)
    {
        if (p_type->low_intr != INVG)
        {
            sub_tbl_id = p_usw_intr_master[lchip]->p_intr_sub_abnormal[p_type->intr].p_array[p_type->sub_intr];
            if (SYS_INTR_GET_TBL_ID(sub_tbl_id) != 0 && (p_type->low_intr < TABLE_FIELD_NUM(lchip, SYS_INTR_GET_TBL_ID(sub_tbl_id))))
            {
                oper_bmp = ((sub_tbl_id >> 16) & 0x3F) | (p_type->core_id ? 0x80 : 0x40);
                sub_tbl_id = (oper_bmp << 16) | (sub_tbl_id & 0xFF00FFFF);
                CTC_ERROR_RETURN(_sys_usw_interrupt_set_en_common(lchip, p_type->low_intr, 1, sub_tbl_id, enable));
            }
        }
        else
        {
            if (MCHIP_INTR(lchip)->interrupt_get_sup_info)
            {
                MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, p_type->intr, &tbl_id, &bit_offset, &sub_tbl_id);
            }
            if (SYS_INTR_GET_TBL_ID(tbl_id) != 0 && (p_type->sub_intr < TABLE_FIELD_NUM(lchip, SYS_INTR_GET_TBL_ID(tbl_id))))
            {
                /* all sup-level table in abnormal intr are core level */
                oper_bmp =  p_type->core_id ? 0x80 : 0x40;
                tbl_id = (oper_bmp << 16) | tbl_id;
                CTC_ERROR_RETURN(_sys_usw_interrupt_set_en_common(lchip, p_type->sub_intr, 1, tbl_id, enable));
            }
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_interrupt_get_en_abnormal(uint8 lchip, sys_intr_type_t* p_type, uint32* p_enable)
{
    uint16 bit_offset = 0;
    uint32 tbl_id = 0;
    uint32 sub_tbl_id = 0;

    if (p_type->sub_intr != INVG)
    {
        if (p_type->low_intr != INVG)
        {
            sub_tbl_id = p_usw_intr_master[lchip]->p_intr_sub_abnormal[p_type->intr].p_array[p_type->sub_intr];
            if (SYS_INTR_GET_TBL_ID(sub_tbl_id) != 0 && (p_type->low_intr < TABLE_FIELD_NUM(lchip, SYS_INTR_GET_TBL_ID(sub_tbl_id))))
            {
                CTC_ERROR_RETURN(_sys_usw_interrupt_get_en_common(lchip, p_type->low_intr, 1, sub_tbl_id, p_enable));
            }
        }
        else
        {
            if (MCHIP_INTR(lchip)->interrupt_get_sup_info)
            {
                MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, p_type->intr, &tbl_id, &bit_offset, &sub_tbl_id);
            }
            if (SYS_INTR_GET_TBL_ID(tbl_id) != 0 && (p_type->sub_intr < TABLE_FIELD_NUM(lchip, SYS_INTR_GET_TBL_ID(tbl_id))))
            {
                CTC_ERROR_RETURN(_sys_usw_interrupt_get_en_common(lchip, p_type->sub_intr, 1, tbl_id, p_enable));
            }
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_interrupt_set_en_func(uint8 lchip, sys_intr_type_t* p_type, uint32 enable)
{
    uint32 tbl_id = 0;
    uint8 oper_bmp = 0;
    uint16 bit_offset = 0;
    uint32 sub_tbl_id = 0;

    if (MCHIP_INTR(lchip)->interrupt_get_sup_info)
    {
        MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, p_type->intr, &tbl_id, &bit_offset, &sub_tbl_id);
    }

    if (p_type->sub_intr != INVG)
    {
        if (sub_tbl_id != - 1)
        {
            /* all sub-tbl-id in func intr are all core level */
            oper_bmp = p_type->core_id ? 0x80 : 0x40;
            sub_tbl_id = (oper_bmp << 16) | sub_tbl_id;
            CTC_ERROR_RETURN(_sys_usw_interrupt_set_en_common(lchip, p_type->sub_intr, 1, sub_tbl_id, enable));
        }
        else
        {
            return CTC_E_INVALID_PARAM;
        }
    }
    else
    {
        /* MapIntrVecFuncLocal in func intr is core level */
        oper_bmp = p_type->core_id ? 0x80 : 0x40;
        tbl_id = (oper_bmp << 16) | tbl_id;
        CTC_ERROR_RETURN(_sys_usw_interrupt_set_en_common(lchip, bit_offset, 1, tbl_id, enable));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_interrupt_get_en_func(uint8 lchip, sys_intr_type_t* p_type, uint32* p_enable)
{
    uint32 tbl_id = 0;
    uint16 bit_offset = 0;
    uint32 sub_tbl_id = 0;

    if (MCHIP_INTR(lchip)->interrupt_get_sup_info)
    {
        MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, p_type->intr, &tbl_id, &bit_offset, &sub_tbl_id);
    }

    if (p_type->sub_intr != INVG)
    {
        if (sub_tbl_id != - 1)
        {
            CTC_ERROR_RETURN(_sys_usw_interrupt_get_en_common(lchip, p_type->sub_intr, 1, sub_tbl_id, p_enable));
        }
        else
        {
            return CTC_E_INVALID_PARAM;
        }
    }
    else
    {
        CTC_ERROR_RETURN(_sys_usw_interrupt_get_en_common(lchip, bit_offset, 1, tbl_id, p_enable));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_at_interrupt_set_en_cpu_sub(uint8 lchip, sys_intr_type_t* p_type, uint32 enable)
{
    uint32 tbl_id = 0;
    uint8 oper_bmp = 0;
    uint16 bit_offset = 0;
    uint32 sub_tbl_id = 0;

    if (MCHIP_INTR(lchip)->interrupt_get_sup_info)
    {
        MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, p_type->intr, &tbl_id, &bit_offset, &sub_tbl_id);
    }

    /* as all cpu-sub interrupt are only sup-level */
    /* the returned tbl_id may include instance num, such as ecpu intr */
    oper_bmp = p_type->core_id ? 0x80 : 0x40;
    tbl_id = (oper_bmp << 16) | tbl_id;
    CTC_ERROR_RETURN(_sys_usw_interrupt_set_en_common(lchip, p_type->sub_intr, 1, tbl_id, enable));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_interrupt_set_mapping(uint8 lchip, sys_intr_group_t* p_group, bool enable)
{
    uint8 index = 0;
    uint8 oper_bmp = 0x40;/* MapCtl only consider core 0 */
    ds_t map_ctl;
    uint32 cmd = 0;
    uint32 intr_bmp = 0;
    uint32 intr_bmp_arr[SYS_INTR_MAX_BMP_NUM] = {0};

    if (DRV_FROM_AT(lchip))
    {
        switch (p_group->irq_idx)
        {
            case 0:
                cmd = DRV_IOR(SupIntrMap0Ctl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, 0, ((uint64)oper_bmp << DRV_BITS_PER_WORD) | cmd, &map_ctl));
                GetSupIntrMap0Ctl(A, supIntrMap_f, &map_ctl, intr_bmp_arr);
                for (index = 0; index < SYS_INTR_MAX_BMP_NUM; index++)
                {
                    intr_bmp_arr[index] = (enable) ? (intr_bmp_arr[index] | p_group->intr_bmp[index]) : (intr_bmp_arr[index] & (~p_group->intr_bmp[index]));
                }
                SetSupIntrMap0Ctl(A, supIntrMap_f, &map_ctl, intr_bmp_arr);
                cmd = DRV_IOW(SupIntrMap0Ctl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, 0, ((uint64)oper_bmp << DRV_BITS_PER_WORD) | cmd, &map_ctl));
                break;

            case 1:
                cmd = DRV_IOR(SupIntrMap1Ctl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, 0, ((uint64)oper_bmp << DRV_BITS_PER_WORD) | cmd, &map_ctl));
                GetSupIntrMap1Ctl(A, supIntrMap_f, &map_ctl, intr_bmp_arr);
                for(index = 0; index < SYS_INTR_MAX_BMP_NUM; index++)
                {
                    intr_bmp_arr[index] = (enable) ? (intr_bmp_arr[index] | p_group->intr_bmp[index]) : (intr_bmp_arr[index] & (~p_group->intr_bmp[index]));
                }
                SetSupIntrMap1Ctl(A, supIntrMap_f, &map_ctl, intr_bmp_arr);
                cmd = DRV_IOW(SupIntrMap1Ctl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, 0, ((uint64)oper_bmp << DRV_BITS_PER_WORD) | cmd, &map_ctl));
                break;

            case 2:
                cmd = DRV_IOR(SupIntrMap2Ctl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, 0, ((uint64)oper_bmp << DRV_BITS_PER_WORD) | cmd, &map_ctl));
                GetSupIntrMap2Ctl(A, supIntrMap_f, &map_ctl, intr_bmp_arr);
                for(index = 0; index < SYS_INTR_MAX_BMP_NUM; index++)
                {
                    intr_bmp_arr[index] = (enable) ? (intr_bmp_arr[index] | p_group->intr_bmp[index]) : (intr_bmp_arr[index] & (~p_group->intr_bmp[index]));
                }
                SetSupIntrMap2Ctl(A, supIntrMap_f, &map_ctl, intr_bmp_arr);
                cmd = DRV_IOW(SupIntrMap2Ctl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, 0, ((uint64)oper_bmp << DRV_BITS_PER_WORD) | cmd, &map_ctl));
                break;

            case 3:
                cmd = DRV_IOR(SupIntrMap3Ctl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, 0, ((uint64)oper_bmp << DRV_BITS_PER_WORD) | cmd, &map_ctl));
                GetSupIntrMap3Ctl(A, supIntrMap_f, &map_ctl, intr_bmp_arr);
                for (index = 0; index < SYS_INTR_MAX_BMP_NUM; index++)
                {
                    intr_bmp_arr[index] = (enable) ? (intr_bmp_arr[index] | p_group->intr_bmp[index]) : (intr_bmp_arr[index] & (~p_group->intr_bmp[index]));
                }
                SetSupIntrMap3Ctl(A, supIntrMap_f, &map_ctl, intr_bmp_arr);
                cmd = DRV_IOW(SupIntrMap3Ctl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, 0, ((uint64)oper_bmp << DRV_BITS_PER_WORD) | cmd, &map_ctl));
                break;

            default:
                break;
        }
        return CTC_E_NONE;
    }

    cmd = DRV_IOR(SupIntrMapCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &map_ctl));

    if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
    {
        switch (p_group->irq_idx)
        {
            case 0:
                GetSupIntrMapCtl(A, supIntrMap0_f, &map_ctl, intr_bmp_arr);
                for (index = 0; index < SYS_INTR_MAX_BMP_NUM; index++)
                {
                    intr_bmp_arr[index] = (enable) ? (intr_bmp_arr[index] | p_group->intr_bmp[index]) : (intr_bmp_arr[index] & (~p_group->intr_bmp[index]));
                }
                SetSupIntrMapCtl(A, supIntrMap0_f, &map_ctl, intr_bmp_arr);
                break;

            case 1:
                GetSupIntrMapCtl(A, supIntrMap1_f, &map_ctl, intr_bmp_arr);
                for(index = 0; index < SYS_INTR_MAX_BMP_NUM; index++)
                {
                    intr_bmp_arr[index] = (enable) ? (intr_bmp_arr[index] | p_group->intr_bmp[index]) : (intr_bmp_arr[index] & (~p_group->intr_bmp[index]));
                }
                SetSupIntrMapCtl(A, supIntrMap1_f, &map_ctl, intr_bmp_arr);
                break;

            case 2:
                GetSupIntrMapCtl(A, supIntrMap2_f, &map_ctl, intr_bmp_arr);
                for(index = 0; index < SYS_INTR_MAX_BMP_NUM; index++)
                {
                    intr_bmp_arr[index] = (enable) ? (intr_bmp_arr[index] | p_group->intr_bmp[index]) : (intr_bmp_arr[index] & (~p_group->intr_bmp[index]));
                }
                SetSupIntrMapCtl(A, supIntrMap2_f, &map_ctl, intr_bmp_arr);
                break;

            case 3:
                GetSupIntrMapCtl(A, supIntrMap3_f, &map_ctl, intr_bmp_arr);
                for (index = 0; index < SYS_INTR_MAX_BMP_NUM; index++)
                {
                    intr_bmp_arr[index] = (enable) ? (intr_bmp_arr[index] | p_group->intr_bmp[index]) : (intr_bmp_arr[index] & (~p_group->intr_bmp[index]));
                }
                SetSupIntrMapCtl(A, supIntrMap3_f, &map_ctl, intr_bmp_arr);
                break;

            default:
                break;
        }
    }
    else
    {
        switch (p_group->irq_idx)
        {
            case 0:
                intr_bmp = GetSupIntrMapCtl(V, supIntrMap0_f, &map_ctl);
                intr_bmp = (enable)? (intr_bmp | p_group->intr_bmp[0]) : (intr_bmp&(~(p_group->intr_bmp[0])));
                SetSupIntrMapCtl(V, supIntrMap0_f, &map_ctl, intr_bmp);
                break;

            case 1:
                intr_bmp = GetSupIntrMapCtl(V, supIntrMap1_f, &map_ctl);
                intr_bmp = (enable)? (intr_bmp | p_group->intr_bmp[0]) : (intr_bmp&(~(p_group->intr_bmp[0])));
                SetSupIntrMapCtl(V, supIntrMap1_f, &map_ctl, intr_bmp);
                break;

            case 2:
                intr_bmp = GetSupIntrMapCtl(V, supIntrMap2_f, &map_ctl);
                intr_bmp = (enable)? (intr_bmp | p_group->intr_bmp[0]) : (intr_bmp&(~(p_group->intr_bmp[0])));
                SetSupIntrMapCtl(V, supIntrMap2_f, &map_ctl, intr_bmp);
                break;

            case 3:
                intr_bmp = GetSupIntrMapCtl(V, supIntrMap3_f, &map_ctl);
                intr_bmp = (enable)? (intr_bmp | p_group->intr_bmp[0]) : (intr_bmp&(~(p_group->intr_bmp[0])));
                SetSupIntrMapCtl(V, supIntrMap3_f, &map_ctl, intr_bmp);
                break;

            default:
                break;
        }
    }

    cmd = DRV_IOW(SupIntrMapCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &map_ctl));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_interrupt_dispatch_dma_func(uint8 lchip)
{
    uint32 cmd = 0;
    uint32 value[2] = {0};
    uint32 mask[2] = {0};
    uint8 oper_bmp = 0;
    uint8 core_id = 0;
    uint8 pp_id = 0;

    if (DRV_FROM_AT(lchip))
    {
        /* dispatch core 0 instance 0 */
        for (core_id = 0; core_id < SYS_AT_INTR_MAX_CORE_NUM; core_id++)
        {
            oper_bmp = core_id ? 0x80 : 0x40;
            cmd = DRV_IOR(DmaCtlIntrFunc0_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, INTR_INDEX_VAL_SET, ((uint64)oper_bmp << DRV_BITS_PER_WORD) | cmd, value));
            cmd = DRV_IOR(DmaCtlIntrFunc0_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, INTR_INDEX_MASK_SET, ((uint64)oper_bmp << DRV_BITS_PER_WORD) | cmd, mask));

            value[0] = (value[0] & (~mask[0]));
            value[1] = (value[1] & (~mask[1]));

            cmd = DRV_IOW(DmaCtlIntrFunc0_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, INTR_INDEX_VAL_RESET, ((uint64)oper_bmp << DRV_BITS_PER_WORD) | cmd, value));

            pp_id = core_id ? PP_NUM_PER_CORE : 0;

            if (value[0] || value[1])
            {
                p_usw_intr_master[lchip]->intr[SYS_INTR_DMA].occur_count++;
                p_usw_intr_master[lchip]->intr[SYS_INTR_DMA].isr(pp_id, SYS_INTR_DMA, value);
            }
        }

    }
    else
    {
        cmd = DRV_IOR(DmaCtlIntrFunc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, INTR_INDEX_VAL_SET, cmd, value));
        cmd = DRV_IOR(DmaCtlIntrFunc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, INTR_INDEX_MASK_SET, cmd, mask));

        value[0] = (value[0] & (~mask[0]));
        value[1] = (value[1] & (~mask[1]));

        cmd = DRV_IOW(DmaCtlIntrFunc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, INTR_INDEX_VAL_RESET, cmd, value));

        if (value[0] || value[1])
        {
            p_usw_intr_master[lchip]->intr[SYS_INTR_DMA].occur_count++;
            p_usw_intr_master[lchip]->intr[SYS_INTR_DMA].isr(lchip, SYS_INTR_DMA, value);
        }
    }

    return CTC_E_NONE;
}


void
_sys_usw_interrupt_dispatch_normal(uint8 lchip, uint32* p_status)
{
    sys_intr_type_t type;
    sys_intr_t* p_intr = NULL;
    uint32 status[CTC_INTR_STAT_SIZE] = {0};

    sal_memset(&type, 0, sizeof(sys_intr_type_t));
    type.core_id = ((lchip - SYS_PP_BASE(lchip)) >= PP_NUM_PER_CORE) ? 1 : 0;

    type.intr = SYS_INTR_CHIP_NORMAL;
    type.sub_intr = INVG;
    type.low_intr = INVG;
    type.lvl4_intr = INVG;

    /*get intr status*/
    CTC_ERROR_DUMP(_sys_usw_interrupt_get_status_normal(lchip, &type, status));

    if ((status[0] == 0) && (status[1] == 0))/* abnormal interrupt with max 2 word bitwidth status */
    {
        type.core_id = ((lchip - SYS_PP_BASE(lchip)) >= PP_NUM_PER_CORE) ? 1 : 0;
    }

    p_intr = &(p_usw_intr_master[lchip]->intr[type.intr]);
    if (p_intr->valid)
    {
        p_intr->occur_count++;
        if (p_intr->isr)
        {
            p_intr->isr(lchip, type.intr, status);
        }
    }

    CTC_ERROR_DUMP(_sys_usw_interrupt_clear_status_normal(lchip, &type, status));
    return;
}

void
_sys_usw_interrupt_dispatch_fatal(uint8 lchip, uint32* p_status)
{
    sys_intr_type_t type;
    sys_intr_t* p_intr = NULL;
    uint32 status[CTC_INTR_STAT_SIZE] = {0};

    sal_memset(&type, 0, sizeof(sys_intr_type_t));    
    type.core_id = ((lchip - SYS_PP_BASE(lchip)) >= PP_NUM_PER_CORE) ? 1 : 0;

    type.intr = SYS_INTR_CHIP_FATAL;
    type.sub_intr = INVG;
    type.low_intr = INVG;
    type.lvl4_intr = INVG;

    /*get intr status*/
    CTC_ERROR_DUMP(_sys_usw_interrupt_get_status_fatal(lchip, &type, status));

    if ((status[0] == 0) && (status[1] == 0))/* abnormal interrupt with max 2 word bitwidth status */
    {
        return;
    }

    p_intr = &(p_usw_intr_master[lchip]->intr[type.intr]);
    if (p_intr->valid)
    {
        p_intr->occur_count++;
        if (p_intr->isr)
        {
            p_intr->isr(lchip, type.intr, status);
        }
    }

    CTC_ERROR_DUMP(_sys_usw_interrupt_clear_status_fatal(lchip, &type, status));
    return;
}

STATIC int32
_sys_usw_interrupt_second_dispatch(uint8 lchip, sys_intr_group_t* p_group)
{
    _sys_usw_interrupt_set_mapping(lchip, p_group, FALSE);

    /*for DMA specific*/
    _sys_usw_interrupt_dispatch_dma_func(lchip);

    CTC_ERROR_RETURN(sal_sem_give(p_group->p_sync_sem));
    return CTC_E_NONE;
}

STATIC void
_sys_usw_interrupt_dispatch(void* p_data)
{
    uint8 lchip = 0;
    uint32 irq = *((uint32*)p_data);
    sys_intr_group_t* p_group = NULL;
    uint32 cmd = 0;
    uint32 status[CTC_INTR_STAT_SIZE]={0};
    uint32 table_id = 0;
    uint8 lchip_num = 0;
    uint8 i = 0;
    uint8 irq_index = 0;
    uint8 index = 0;
    uint8 occur_flag = 0;
    uint8 occur_intr_lchip[CTC_MAX_LOCAL_CHIP_NUM_PP] = {0};
    uint8 occur_chip_num = 0;
    uint8 lchip_idx = 0;

    /* get lchip num */
    lchip_num = sys_usw_get_local_chip_num();
    for (lchip_idx = 0; lchip_idx < lchip_num; lchip_idx++)
    {
        if (!dal_get_ldev_active(lchip_idx))
        {
            continue;
        }
        lchip = CTC_MAP_LCHIP(lchip_idx);
        
        if(sys_usw_chip_check_active(lchip))
        {
           continue;
        }

        for(i = 0; i < p_usw_intr_master[lchip]->group_count; i++)
        {
            occur_flag = 0;

            if(irq != p_usw_intr_master[lchip]->group[i].irq)
            {
                continue;
            }
            

            /*get IRQ group information */
            p_group = &(p_usw_intr_master[lchip]->group[i]);
            irq_index = p_group->irq_idx;

            /*mask group interrupt*/
             MCHIP_INTR(lchip)->interrupt_set_sup_op(lchip, p_group->irq_idx, INTR_INDEX_MASK_SET);
            occur_intr_lchip[occur_chip_num] = lchip;
            occur_chip_num++;

            /* 1. get sup interrupt status */
            table_id = SupCtlIntrVec_t;
            cmd = DRV_IOR(table_id, DRV_ENTRY_FLAG);
            sal_memset(status, 0, sizeof(status));
            (DRV_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &status));

            /* get groups mask */
            for (index = 0; index < p_usw_intr_master[lchip]->intr_word_num; index++)
            {
                status[index] = (status[index] & p_group->intr_bmp[index]);
                if (0 != status[index])
                {
                    occur_flag = 1;
                }
            }

            if (occur_flag == 0)
            {
                continue;
            }
            p_group->occur_count++;

            if(!p_group->p_sync_task)
            {
                if (status[0] &  CTC_INTR_T2B(SYS_INTR_CHIP_NORMAL))
                {
                    p_usw_intr_master[lchip]->dispatch_normal(lchip, status);
                }

                if (status[0] & CTC_INTR_T2B(SYS_INTR_CHIP_FATAL))
                {
                    p_usw_intr_master[lchip]->dispatch_fatal(lchip, status);
                }

                if ((status[3] >> 16) & CTC_INTR_T2B(SYS_INTR_CHIP_NORMAL))
                {
                    p_usw_intr_master[lchip]->dispatch_normal(lchip + SYS_PP_NUM(lchip)/2, status);
                }

                if ((status[3] >> 16) & CTC_INTR_T2B(SYS_INTR_CHIP_FATAL))
                {
                    p_usw_intr_master[lchip]->dispatch_fatal(lchip + SYS_PP_NUM(lchip)/2, status);
                }

                /*Process sup level function interrupt*/
                MCHIP_INTR(lchip)->interrupt_dispatch_func(lchip, status);
            }
            else if(p_group->p_sync_task) /* second dispatch */
            {
                _sys_usw_interrupt_second_dispatch(lchip, p_group);
            }
        }

        /* before release cpu interrupt, reset chip interrupt */
        MCHIP_INTR(lchip)->interrupt_set_sup_op(lchip, irq_index, INTR_INDEX_VAL_RESET);
    }

    /*release CPU interrupt*/
    g_dal_op.interrupt_set_en(irq, TRUE);

    /*release chip interrupt*/
    for(i = 0; i < occur_chip_num; i++)
    {
        lchip = occur_intr_lchip[i];
        if(sys_usw_chip_check_active(lchip))
        {
           continue;
        }
       MCHIP_INTR(lchip)->interrupt_set_sup_op(occur_intr_lchip[i], irq_index, INTR_INDEX_MASK_RESET);
    }

    return;

}

int32
_sys_usw_interrupt_release_fatal(uint8 lchip, sys_intr_type_t* p_type, uint32 enable)
{
    uint32 sub_tbl_id = 0;
    uint32 tbl_id_low = 0;
    uint32 cmd = 0;
    int32 ret = CTC_E_NONE;
    uint32 value_a = 0;
    uint32 mask[CTC_INTR_STAT_SIZE];
    uint32 sub_ins_id = 0;
    uint32 low_ins_id = 0;

    CTC_BMP_INIT(mask);
    /* relase mask of all fatal interrupt */
    INTR_SUB_TYPE_CHECK(p_type->sub_intr, p_usw_intr_master[lchip]->fatal_sub_cnt);

    /* now only support mask */
    if (!enable)
    {
        ret = CTC_E_NOT_SUPPORT;
        return ret;
    }

    sub_tbl_id = SYS_INTR_GET_TBL_ID(p_usw_intr_master[lchip]->p_intr_sub_abnormal[SYS_INTR_CHIP_FATAL].p_array[p_type->sub_intr]);
    sub_ins_id = SYS_INTR_GET_TBL_INS_ID(p_usw_intr_master[lchip]->p_intr_sub_abnormal[SYS_INTR_CHIP_FATAL].p_array[p_type->sub_intr]);
    /* TO_DO */
    if (p_usw_intr_master[lchip]->p_intr_low_fatal[p_type->sub_intr].array_size && ((p_type->sub_intr > 2 && p_type->sub_intr < 15) || (DRV_FROM_TMM(lchip))))
    {
        tbl_id_low =  SYS_INTR_GET_TBL_ID(p_usw_intr_master[lchip]->p_intr_low_fatal[p_type->sub_intr].p_array[p_type->low_intr]);
        low_ins_id = SYS_INTR_GET_TBL_INS_ID(p_usw_intr_master[lchip]->p_intr_low_fatal[p_type->sub_intr].p_array[p_type->low_intr]);
        if(tbl_id_low == PbCtlInterruptFatal_t && DRV_IS_TSINGMA(lchip) && (SYS_GET_CHIP_VERSION == SYS_CHIP_SUB_VERSION_B))
        {
            tbl_id_low = 0;
        }
    }

    if (tbl_id_low != 0)
    {
        /* clear mask of low-level interrupt */
        cmd = DRV_IOR(tbl_id_low, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, DRV_INS(low_ins_id, INTR_INDEX_MASK_SET), cmd, mask);
        cmd = DRV_IOW(tbl_id_low, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, DRV_INS(low_ins_id, INTR_INDEX_MASK_RESET), cmd, mask);
    }

    if (sub_tbl_id != 0)
    {
        /* clear mask of sub-level interrupt */
        cmd = DRV_IOR(sub_tbl_id, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, DRV_INS(sub_ins_id, INTR_INDEX_MASK_SET), cmd, mask);
        cmd = DRV_IOW(sub_tbl_id, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, DRV_INS(sub_ins_id, INTR_INDEX_MASK_RESET), cmd, mask);
    }

    /* clear mask of sup-level interrupt */
    value_a = (1 << p_type->sub_intr);
    cmd = DRV_IOW(SupIntrFatal_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, INTR_INDEX_MASK_RESET, cmd, &value_a);

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_set_interrupt_en(uint8 lchip, uint32 value)
{
    uint32 cmd = 0;
    SupIntrCtl_m intr_ctl;

    cmd = DRV_IOR(SupIntrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &intr_ctl));
    if (value)
    {
        SetSupIntrCtl(V, funcIntrEn_f, &intr_ctl, 1);
        SetSupIntrCtl(V, interruptEn_f, &intr_ctl, 1);
        if(p_usw_intr_master[lchip]->intr_mode)
        {
            SetSupIntrCtl(V, padIntrEn_f, &intr_ctl, 0);
            SetSupIntrCtl(V, pcie0IntrEn_f, &intr_ctl, 1);
            SetSupIntrCtl(V, pcieIntrEn_f, &intr_ctl, 1);
        }
        else
        {
            SetSupIntrCtl(V, padIntrEn_f, &intr_ctl, 1);
            SetSupIntrCtl(V, pcie0IntrEn_f, &intr_ctl, 0);
            SetSupIntrCtl(V, pcieIntrEn_f, &intr_ctl, 0);
        }
    }
    else
    {
        SetSupIntrCtl(V, funcIntrEn_f, &intr_ctl, 0);
        SetSupIntrCtl(V, interruptEn_f, &intr_ctl, 0);
        SetSupIntrCtl(V, padIntrEn_f, &intr_ctl, 0);
        SetSupIntrCtl(V, pcie0IntrEn_f, &intr_ctl, 0);
        SetSupIntrCtl(V, pcieIntrEn_f, &intr_ctl, 0);
    }
    cmd = DRV_IOW(SupIntrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &intr_ctl));

    return CTC_E_NONE;
}

int32
_sys_usw_interrupt_release_normal(uint8 lchip, sys_intr_type_t* p_type, uint32 enable)
{
    uint32 sub_tbl_id = 0;
    uint32 tbl_id_low = 0;
    uint32 cmd = 0;
    int32 ret = CTC_E_NONE;
    uint32 value_a[CTC_INTR_STAT_SIZE] = {0};
    uint32 mask[CTC_INTR_STAT_SIZE] = {0};
    uint32 sub_ins_id = 0;
    uint32 low_ins_id = 0;

    CTC_BMP_INIT(mask);
    /* relase mask of all fatal interrupt */
    INTR_SUB_TYPE_CHECK(p_type->sub_intr, p_usw_intr_master[lchip]->normal_sub_cnt);

    /* now only support mask */
    if (!enable)
    {
        ret = CTC_E_NOT_SUPPORT;
        return ret;
    }

    sub_tbl_id = SYS_INTR_GET_TBL_ID(p_usw_intr_master[lchip]->p_intr_sub_abnormal[SYS_INTR_CHIP_NORMAL].p_array[p_type->sub_intr]);
    sub_ins_id = SYS_INTR_GET_TBL_INS_ID(p_usw_intr_master[lchip]->p_intr_sub_abnormal[SYS_INTR_CHIP_NORMAL].p_array[p_type->sub_intr]);
    if (DRV_FROM_TMM(lchip) && (sub_tbl_id == CtcMiscCtlInterruptNormal_t || sub_tbl_id == DmaCtlInterruptNormal_t
        || sub_tbl_id == McPcsX16LanesInterruptNormal_t))
    {
        return CTC_E_NONE;
    }
    if(p_usw_intr_master[lchip]->p_intr_low_normal[p_type->sub_intr].array_size)
    {
        tbl_id_low = SYS_INTR_GET_TBL_ID(p_usw_intr_master[lchip]->p_intr_low_normal[p_type->sub_intr].p_array[p_type->low_intr]);
        low_ins_id = SYS_INTR_GET_TBL_INS_ID(p_usw_intr_master[lchip]->p_intr_low_normal[p_type->sub_intr].p_array[p_type->low_intr]);
        if ((tbl_id_low != 0 && p_type->sub_intr > 2) || DRV_FROM_TMM(lchip))
        {
            /* clear mask of low-level interrupt */
            cmd = DRV_IOR(tbl_id_low, DRV_ENTRY_FLAG);
            DRV_IOCTL(lchip, DRV_INS(low_ins_id, INTR_INDEX_MASK_SET), cmd, mask);

            if (tbl_id_low == McMacInterruptNormal_t && DRV_FROM_TMM(lchip))
            {
                mask[0] = 0;  /*intRxLintFaul*/
                mask[1] = 0;  /*intRxLintFault/intRxRemoteFault*/
                mask[2] = 0;  /*intRxLintFault/intRxRemoteFault*/
                mask[3] = 0;  /*intRxLocalFault*/
                mask[4] = 0;  /*intRxLinkFault*/
                mask[5] = 0;  /*intMcMacTxPauseTypeMismatch*/
                mask[6] = 0;  /*intMcMacTxPauseTypeMismatch/intMcMacRxPauseTypeMismatch*/
                mask[7] = 0xFFFF0000;  /*intMcMacRxPauseTypeMismatch/intMcMacRxPauseLockDetect*/
                mask[8] = 0x00FFFFFF;  /*intMcMacRxPauseLockDetect/intMcMacRxBuffOverrun*/
                mask[9] = 0;  /*intMcMacRxBuffOverrun*/
            }
            cmd = DRV_IOW(tbl_id_low, DRV_ENTRY_FLAG);
            DRV_IOCTL(lchip, DRV_INS(low_ins_id, INTR_INDEX_MASK_RESET), cmd, mask);
        }
    }

    /* TO_DO */
    if(sub_tbl_id != 0 && sub_tbl_id != RlmCsCtlInterruptNormal_t && sub_tbl_id != RlmHsCtlInterruptNormal_t && 
      McuSupInterruptNormal0_t != sub_tbl_id && McuSupInterruptNormal1_t != sub_tbl_id && 
      McuSupInterruptNormal2_t != sub_tbl_id && McuSupInterruptNormal3_t != sub_tbl_id)
    {
        /* clear mask of sub-level interrupt */
        cmd = DRV_IOR(sub_tbl_id, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, DRV_INS(sub_ins_id, INTR_INDEX_MASK_SET), cmd, mask);

        cmd = DRV_IOW(sub_tbl_id, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, DRV_INS(sub_ins_id, INTR_INDEX_MASK_RESET), cmd, mask);
    }

    /* clear mask of sup-level interrupt */
    CTC_BMP_SET(value_a, p_type->sub_intr);
    cmd = DRV_IOW(SupIntrNormal_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, INTR_INDEX_MASK_RESET, cmd, &value_a);

    /* clear mask of sub-level interrupt */
    if (!DRV_FROM_TMM(lchip))
    {
        mask[0] = 0xc000f080;
        mask[1] = 0x07;

        cmd = DRV_IOW(DmaCtlInterruptNormal_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, INTR_INDEX_MASK_SET, cmd, mask);
    }

    return CTC_E_NONE;
}

int32
_sys_usw_interrupt_init_reg(uint8 lchip)
{
    if (p_usw_intr_master[lchip]->init_done == 2)
    {
        /*reloading process do not write register*/
        p_usw_intr_master[lchip]->init_done = 1;
        return CTC_E_NONE;
    }

    if (MCHIP_INTR(lchip)->interrupt_init_reg)
    {
        CTC_ERROR_RETURN(MCHIP_INTR(lchip)->interrupt_init_reg(lchip));
    }

    return CTC_E_NONE;
}

#define __ADD_FOR_SECOND_DISPATCH__
STATIC int32
_sys_usw_interrupt_get_irq_info(uint8 lchip, uint8* irq_cnt, sys_intr_irq_info_t* irq_array, uint8 intr_mode)
{
    uint8 i = 0;
    uint8 cnt = 0;
    uint8 tmp_cnt = 0;
    uint8 sort_flag = 1;
    sys_intr_irq_info_t tmp_info;
    sys_intr_irq_info_t per_group_irq_info[SYS_USW_MAX_INTR_GROUP];

    sal_memset(&tmp_info, 0, sizeof(tmp_info));
    sal_memset(per_group_irq_info, 0, sizeof(per_group_irq_info));
    cnt = p_usw_intr_master[lchip]->group_count;

    /*for legacy interrupt,only support one irq, so,all the interrupt mappin to one irq*/
    if(intr_mode == CTC_INTR_MODE_LEGACY)
    {
        for(i=0; i<cnt; ++i)
        {
            p_usw_intr_master[lchip]->group[i].irq_idx = 0;
            p_usw_intr_master[lchip]->group[i].irq = p_usw_intr_master[lchip]->group[0].irq;
        }
    }

    for(i=0; i<cnt; ++i)
    {
        per_group_irq_info[i].irq = p_usw_intr_master[lchip]->group[i].irq;
        per_group_irq_info[i].irq_idx = p_usw_intr_master[lchip]->group[i].irq_idx;
        /*per_group_irq_info's index is group, so only use per_group_irq_info[i].group[0]*/
        per_group_irq_info[i].group[0] = p_usw_intr_master[lchip]->group[i].group;
        per_group_irq_info[i].prio = p_usw_intr_master[lchip]->group[i].prio;
    }

    /*sort according irq value*/
    tmp_cnt = cnt;
    while(sort_flag)
    {
        sort_flag = 0;
        for(i=1;i<tmp_cnt;++i)
        {
            if(per_group_irq_info[i-1].irq_idx > per_group_irq_info[i].irq_idx)
            {
                sal_memcpy(&tmp_info,per_group_irq_info+i-1,sizeof(sys_intr_irq_info_t));
                sal_memcpy(per_group_irq_info+i-1,per_group_irq_info+i,sizeof(sys_intr_irq_info_t));
                sal_memcpy(per_group_irq_info+i,&tmp_info,sizeof(sys_intr_irq_info_t));

                sort_flag = 1;
            }
        }
        tmp_cnt--;
    }

    /*init the first irq info*/
    sal_memcpy(irq_array,per_group_irq_info,sizeof(sys_intr_irq_info_t));
    irq_array[0].group_count = 1;
    *irq_cnt = 1;

    /*get the highest prio and group count for per irq*/
    for(i=1; i<cnt; i++)
    {
        if(per_group_irq_info[i-1].irq_idx != per_group_irq_info[i].irq_idx)
        {
            (*irq_cnt)++;
            irq_array[*irq_cnt-1].irq = per_group_irq_info[i].irq;
            irq_array[*irq_cnt-1].irq_idx = per_group_irq_info[i].irq_idx;
            irq_array[*irq_cnt-1].prio = per_group_irq_info[i].prio;
            irq_array[*irq_cnt-1].group_count = 1;
            irq_array[*irq_cnt-1].group[0] = per_group_irq_info[i].group[0];
        }
        else
        {
            if(irq_array[*irq_cnt-1].prio > per_group_irq_info[i].prio)
            {
                irq_array[*irq_cnt-1].prio = per_group_irq_info[i].prio;
            }

            irq_array[*irq_cnt-1].group_count++;
            irq_array[*irq_cnt-1].group[(irq_array[*irq_cnt-1].group_count-1)] = per_group_irq_info[i].group[0];
        }
    }

    return CTC_E_NONE;
}

STATIC void
_sys_usw_interrupt_sync_thread(void* param)
{
    uint8 lchip = 0;
    int32 ret = 0;
    uint32 cmd = 0;
    uint32 status[CTC_INTR_STAT_SIZE] = {0};
    sys_intr_group_t* p_group = (sys_intr_group_t*)param;
    sys_intr_type_t type;
    uint8  index = 0;
    uint8  oper_bmp = 0x40; /* only consider status in core 0 */
    uint32 table_id = 0;

    lchip = p_group->lchip;
    sal_memset(&type,0,sizeof(type));
    while(1)
    {
        ret = sal_sem_take(p_group->p_sync_sem, SAL_SEM_FOREVER);
        if (0 != ret)
        {
            continue;
        }
        SYS_LCHIP_CHECK_ACTIVE_IN_THREAD(lchip);
        SYS_CHIP_CHECK_RESET_HW_IN_THREAD(lchip);
        INTR_LOCK;
        if( !p_usw_intr_master[lchip]->init_done)
        { /*the chip is inactive, thread should be exit*/
           INTR_UNLOCK;
           return ;
        }

        sal_memset(status, 0, CTC_INTR_STAT_SIZE * sizeof(uint32));
        /* 1. get sup interrupt status */
        table_id = SupCtlIntrVec_t;
        cmd = DRV_IOR(table_id, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL_BMP(lchip, INTR_INDEX_VAL_SET, ((uint64)oper_bmp << DRV_BITS_PER_WORD) | cmd, &status);
        if (0 != ret)
        {
            continue;
        }

        /* 2. get groups mask */
        for (index = 0; index < p_usw_intr_master[lchip]->intr_word_num; index++)
        {
            status[index] = status[index] & p_group->intr_bmp[index];
        }


        /* 3. process interrupt */
        if (status[0] & CTC_INTR_T2B(SYS_INTR_CHIP_NORMAL))
        {
            p_usw_intr_master[lchip]->dispatch_normal(lchip, status);
        }

        if (status[0] & CTC_INTR_T2B(SYS_INTR_CHIP_FATAL))
        {
            p_usw_intr_master[lchip]->dispatch_fatal(lchip, status);
        }

        if ((status[3] >> 16) & CTC_INTR_T2B(SYS_INTR_CHIP_NORMAL))
        {
            p_usw_intr_master[lchip]->dispatch_normal(lchip + SYS_PP_NUM(lchip)/2, status);
        }

        if ((status[3] >> 16) & CTC_INTR_T2B(SYS_INTR_CHIP_FATAL))
        {
            p_usw_intr_master[lchip]->dispatch_fatal(lchip + SYS_PP_NUM(lchip)/2, status);
        }

        /*Process sup level function interrupt*/
        MCHIP_INTR(lchip)->interrupt_dispatch_func(lchip, status);

        /* 4. mask sup interrupt */
        _sys_usw_interrupt_set_mapping(lchip, p_group, TRUE);

        INTR_UNLOCK;
    }

    return;
}

STATIC int32
_sys_usw_interrupt_init_thread(uint8 lchip, sys_intr_group_t* p_group)
{
    int32 ret = 0;
    char buffer[32];
    uint8 group_id = 0;
    uint16 prio = 0;
    uint64 cpu_mask = 0;

    group_id = p_group->group;
    prio     = p_group->prio;
    sal_sprintf(buffer, "interrupt_group%d", group_id);

    cpu_mask = sys_usw_chip_get_affinity(lchip, 0);
    ret = sys_usw_task_create(lchip,&p_group->p_sync_task, buffer,
                           SAL_DEF_TASK_STACK_SIZE, prio,SAL_TASK_TYPE_INTERRUPT, cpu_mask, _sys_usw_interrupt_sync_thread, (void*)p_group);
    if (ret < 0)
    {
        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
        return CTC_E_NOT_INIT;

    }

    return CTC_E_NONE;
}

STATIC void
_sys_usw_interrupt_poll_thread(void* param)
{
    uint8 lchip = 0;
    sys_intr_group_t* p_group = (sys_intr_group_t*)param;

    lchip = p_group->lchip;
    while(1)
    {
        SYS_LCHIP_CHECK_ACTIVE_IN_THREAD(lchip);
        SYS_CHIP_CHECK_RESET_HW_IN_THREAD(lchip);
        _sys_usw_interrupt_dispatch((void*)&(p_group->irq));
        sal_task_sleep(p_group->interval);
    }

    return;
}

STATIC int32
_sys_usw_interrupt_init_poll_thread(uint8 lchip, sys_intr_group_t* p_group)
{
    int32 ret = 0;
    char buffer[32];
    uint8 group_id = 0;
    uint16 prio = 0;
    uint64 cpu_mask = 0;

    if (0 == p_group->interval)
    {
        p_group->interval = SYS_INTR_DEFAULT_POLL_INTERVAL;
    }
    group_id = p_group->group;
    prio     = p_group->prio;
    sal_sprintf(buffer, "interrupt_poll%d", group_id);

    cpu_mask = sys_usw_chip_get_affinity(lchip, 0);
    ret = sys_usw_task_create(lchip,&p_group->p_poll_task, buffer,
                           SAL_DEF_TASK_STACK_SIZE, prio,SAL_TASK_TYPE_INTERRUPT, cpu_mask, _sys_usw_interrupt_poll_thread, (void*)p_group);
    if (ret < 0)
    {
        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
        return CTC_E_NOT_INIT;

    }

    return CTC_E_NONE;
}

#define __DEBUG_SHOW__
STATIC int32
_sys_usw_interrupt_dump_intr(uint8 lchip, sys_intr_t* p_intr)
{
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-9d %-9d %-9d %-10p %-10s\n", p_intr->group, p_intr->intr, p_intr->occur_count, p_intr->isr, p_intr->desc);
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_interrupt_dump_group(uint8 lchip, sys_intr_group_t* p_group, uint8 is_detail)
{
    sys_intr_t* p_intr = NULL;
    uint32 i = 0;
    int32 ret = 0;
    uint32 offset = 0;

    if (p_group->group < 0)
    {
        return CTC_E_NONE;
    }

    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Group %u: \n", p_group->group);
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-30s:%-6u \n", "--Group IRQ", p_group->irq);
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-30s:%-6u \n", "--ISR Priority", p_group->prio);
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-30s:%-6u \n", "--Occur Count", p_group->occur_count);
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-30s:%-6u \n", "--Interrupt Count", p_group->intr_count);

    if (is_detail)
    {
        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"\n%-9s %-9s %-9s %-10s %-10s\n", "Group", "Interrupt", "Count", "ISR", "Desc");
        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"----------------------------------------------------\n");

        for (i = 0; i < SYS_INTR_MAX; i++)
        {
            if (MCHIP_INTR(lchip)->interrupt_get_intrvec_offset)
            {
                ret = MCHIP_INTR(lchip)->interrupt_get_intrvec_offset(lchip, i, &offset);
                if (ret)
                {
                    continue;
                }
            }

            if (CTC_BMP_ISSET(p_group->intr_bmp, offset))
            {
                p_intr = &(p_usw_intr_master[lchip]->intr[i]);
                if (p_intr->valid)
                {
                    _sys_usw_interrupt_dump_intr(lchip, p_intr);
                }
            }
        }
    }

    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"\n");

    return CTC_E_NONE;
}
/* from Arctic this func do not support */
int32
_sys_usw_interrupt_dump_group_reg(uint8 lchip)
{
    ds_t map_ctl;
    ds_t gen_ctl;
    uint32 cmd = 0;
    uint32 tbl_id = 0;
    uint32 value = 0;

    if (!p_usw_intr_master[lchip]->init_done)
    {
        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
        return CTC_E_NOT_INIT;
    }

    if (DRV_FROM_AT(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }

    sal_memset(&map_ctl, 0, sizeof(map_ctl));
    sal_memset(&gen_ctl, 0, sizeof(gen_ctl));

    tbl_id = SupIntrMapCtl_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &map_ctl));
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Group - Interrupt Mapping reg (%d, %s)\n", tbl_id, DRV_TABLE_NAME(lchip, tbl_id));
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %-8s\n", "Index", "Value");
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"--------------------------------------------------------\n");
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %08X\n", "Valid", 0x3FFFFFFF);

    GetSupIntrMapCtl(A, supIntrMap0_f, &map_ctl, &value);
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %08X\n", "Group0", value);
    GetSupIntrMapCtl(A, supIntrMap1_f, &map_ctl, &value);
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %08X\n", "Group1", value);
    GetSupIntrMapCtl(A, supIntrMap2_f, &map_ctl, &value);
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %08X\n", "Group2", value);
    GetSupIntrMapCtl(A, supIntrMap3_f, &map_ctl, &value);
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %08X\n", "Group3", value);
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"\n");

    tbl_id = SupIntrGenCtl_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &gen_ctl));
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Group reg (%d, %s)\n", tbl_id, DRV_TABLE_NAME(lchip, tbl_id));
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %-8s\n", "Index", "Value");
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"--------------------------------------------------------\n");
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %08X\n", "Valid", 0xFF);
    GetSupIntrGenCtl(A, supIntrValueSet_f, &gen_ctl, &value);
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %08X\n", "ValueSet", value);
    GetSupIntrGenCtl(A, supIntrValueClr_f, &gen_ctl, &value);
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %08X\n", "ValueReset", value);
    GetSupIntrGenCtl(A, supIntrMaskSet_f, &gen_ctl, &value);
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %08X\n", "MaskSet", value);
    GetSupIntrGenCtl(A, supIntrMaskClr_f, &gen_ctl, &value);
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %08X\n", "MaskReset", value);

    /* TODO : Pcie0IntrLogCtl_t / Pcie1IntrLogCtl_t / SupIntrCtl_t / SupCtlVec_t */

    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"\n");
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_interrupt_dump_one_reg(uint8 lchip, uint32 tbl_id)
{
    uint32 cmd = 0;
    uint32 index = 0;
    uint32 value[INTR_INDEX_MAX][CTC_INTR_STAT_SIZE];
    uint32 valid[CTC_INTR_STAT_SIZE];
    tables_info_t* p_tbl = NULL;
    fields_t* p_fld = NULL;
    uint32 fld_id = 0;
    uint32 i = 0;
    uint32 bits = 0;
    uint32 addr_offset = 0;

    sal_memset(valid, 0, sizeof(valid));
    sal_memset(value, 0, sizeof(value));

     /*SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"reg (%d, %s) desc %s intr [%d, %d]\n", tbl_id, DRV_TABLE_NAME(lchip, tbl_id), p_reg->desc,*/
      /*   p_reg->intr_start, (p_reg->intr_start+ p_reg->intr_count - 1));*/

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, INTR_INDEX_VAL_SET, cmd, value[INTR_INDEX_VAL_SET]));
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, INTR_INDEX_VAL_RESET, cmd, value[INTR_INDEX_VAL_RESET]));
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, INTR_INDEX_MASK_SET, cmd, value[INTR_INDEX_MASK_SET]));
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, INTR_INDEX_MASK_RESET, cmd, value[INTR_INDEX_MASK_RESET]));

    p_tbl = TABLE_INFO_PTR(lchip, tbl_id);

    for (fld_id = 0; fld_id < p_tbl->field_num; fld_id++)
    {
        p_fld = &(p_tbl->ptr_fields[fld_id]);
        if (p_fld->seg_num)
        {
            for (i = 0; i < p_fld->ptr_seg[0].bits; i++)
            {
                CTC_BIT_SET(valid[p_fld->ptr_seg[0].word_offset], (p_fld->ptr_seg[0].start + i));
                bits++;
            }
        }
    }

    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %-8s   %s\n", "Index", "Address", "Value");
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"--------------------------------------------------------\n");

    for (i = 0; i < DRV_TABLE_ENTRY_SIZE(lchip, tbl_id)/4; i++)
    {
        /* Valid */
        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %-8d   %08X\n", "Valid", bits, valid[i]);

        /* Value */
        for (index = 0; index < INTR_INDEX_MAX; index++)
        {
            SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-10s %08X   %08X\n", _sys_usw_interrupt_index_str(lchip, index),
                          (uint32)(DRV_TABLE_DATA_BASE(lchip, tbl_id, addr_offset) + (i * 16) + (index * 4)),
                          value[index][i]);
        }

        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"\n");
    }

    return CTC_E_NONE;
}
/**
 @brief Display interrupt register values in chip
 type 1 : group
 type 2 : fatal
 type 3 : normal
 type 4 : func
 type 5 : pcie
 type 6 : dma-func
 type 7 : all
*/
/* from Arctic this func do not support */
int32
sys_usw_interrupt_dump_reg(uint8 lchip, uint32 type)
{
    uint16 bit_offset = 0;
    uint32 tbl_id = 0;
    uint32 sub_tbl_id = 0;
    LCHIP_CHECK(lchip);
    SYS_INTR_INIT_CHECK(lchip);
    if(type == 0 || type > 7)
    {
        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Invalid type: %d\n", type);
        return CTC_E_INVALID_PARAM;
    }

    if (!MCHIP_INTR(lchip)->interrupt_get_sup_info)
    {
        return CTC_E_INVALID_PTR;
    }

    if (DRV_FROM_AT(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }

    if (type == 1 || type == 7)
    {
        _sys_usw_interrupt_dump_group_reg(lchip);
    }

    if (type == 2 || type == 7)
    {
        MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, SYS_INTR_CHIP_FATAL, &tbl_id, &bit_offset, NULL);
        _sys_usw_interrupt_dump_one_reg(lchip, tbl_id);
    }

    if (type == 3 || type == 7)
    {
        MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, SYS_INTR_CHIP_NORMAL, &tbl_id, &bit_offset, NULL);
        _sys_usw_interrupt_dump_one_reg(lchip, tbl_id);
    }

    if (type == 4 || type == 7)
    {
        MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, SYS_INTR_PCS_LINK_31_0, &tbl_id, &bit_offset, &sub_tbl_id);
        if (!sub_tbl_id)
        {
            _sys_usw_interrupt_dump_one_reg(lchip, sub_tbl_id);
        }

        MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, SYS_INTR_PCS_LINK_47_32, &tbl_id, &bit_offset, &sub_tbl_id);
        if (!sub_tbl_id)
        {
            _sys_usw_interrupt_dump_one_reg(lchip, sub_tbl_id);
        }
    }

    if (type == 5 || type == 7)
    {
        MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, SYS_INTR_PCIE_BURST_DONE, &tbl_id, &bit_offset, &sub_tbl_id);
        if (!sub_tbl_id)
        {
            _sys_usw_interrupt_dump_one_reg(lchip, sub_tbl_id);
        }
    }

    if (type == 6 || type == 7)
    {
        MCHIP_INTR(lchip)->interrupt_get_sup_info(lchip, SYS_INTR_DMA, &tbl_id, &bit_offset, &sub_tbl_id);
        if (!sub_tbl_id)
        {
            _sys_usw_interrupt_dump_one_reg(lchip, sub_tbl_id);
        }

    }

    return CTC_E_NONE;
}

/**
 @brief Display interrupt database values in software
*/
int32
sys_usw_interrupt_dump_db(uint8 lchip)
{
    uint32 i = 0;

    LCHIP_CHECK(lchip);
    lchip = SYS_PP_BASE(lchip);
    SYS_INTR_INIT_CHECK(lchip);

    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Using %s global configuration\n", p_usw_intr_master[lchip]->is_default ? "default" : "parameter");
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Group Count:      %d\n", p_usw_intr_master[lchip]->group_count);
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Interrupt Count:  %d\n", p_usw_intr_master[lchip]->intr_count);

    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"\n");
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Registered Interrupts:\n");

    for (i = 0; i < SYS_USW_MAX_INTR_GROUP; i++)
    {
        _sys_usw_interrupt_dump_group(lchip, &(p_usw_intr_master[lchip]->group[i]), 1);
    }

    return CTC_E_NONE;
}

int32
sys_usw_interrupt_parser_type(uint8 lchip, ctc_intr_type_t type)
{
    uint32 tbl_id = 0;
    uint16 intr_base = 0;

    LCHIP_CHECK(lchip);
    SYS_INTR_INIT_CHECK(lchip);

    if (type.intr == SYS_INTR_CHIP_FATAL)
    {
        if (type.sub_intr >= p_usw_intr_master[lchip]->fatal_sub_cnt || p_usw_intr_master[lchip]->p_intr_sub_abnormal[type.intr].p_array[type.sub_intr] == 0)
        {
            return CTC_E_NONE;
        }

        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Fatal Interrupr:\n    sub-intr-table:%s\n", DRV_TABLE_NAME(lchip, SYS_INTR_GET_TBL_ID(p_usw_intr_master[lchip]->p_intr_sub_abnormal[type.intr].p_array[type.sub_intr])));

        /*print low intr table*/
        if (type.low_intr >= p_usw_intr_master[lchip]->p_intr_low_fatal[type.sub_intr].array_size || p_usw_intr_master[lchip]->p_intr_low_fatal[type.sub_intr].p_array[type.low_intr] == 0)
        {
            return CTC_E_NONE;
        }

        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    low-intr-table:%s\n", DRV_TABLE_NAME(lchip, SYS_INTR_GET_TBL_ID(p_usw_intr_master[lchip]->p_intr_low_fatal[type.sub_intr].p_array[type.low_intr])));

        if (DRV_FROM_AT(lchip))
        {
            intr_base = p_usw_intr_master[lchip]->fatal_sub_base ? p_usw_intr_master[lchip]->fatal_sub_base[type.sub_intr] : 0;
            if (type.lvl4_intr >= p_usw_intr_master[lchip]->p_intr_fatal_end_tbl[type.low_intr + intr_base].array_size ||
                p_usw_intr_master[lchip]->p_intr_fatal_end_tbl[type.low_intr + intr_base].p_array[type.lvl4_intr] == 0)
            {
                tbl_id = p_usw_intr_master[lchip]->p_intr_low_fatal[type.sub_intr].p_array[type.low_intr];
                if (MEM_TYPE_PER_CORE != TABLE_ENTRY_TYPE(lchip, SYS_INTR_GET_TBL_ID(tbl_id)) || SYS_INTR_GET_TBL_INS_ID(tbl_id))
                {
                    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    [");
                    if (MEM_TYPE_PER_CORE != TABLE_ENTRY_TYPE(lchip, SYS_INTR_GET_TBL_ID(tbl_id)))
                    {
                        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP," oper_bmp:0x%x ", SYS_INTR_GET_TBL_BMP(tbl_id));
                    }
                    if (SYS_INTR_GET_TBL_INS_ID(tbl_id))
                    {
                        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP," instance_id:%u ", SYS_INTR_GET_TBL_INS_ID(tbl_id));
                    }
                    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"]\n");
                }
                return CTC_E_NONE;
            }

            tbl_id = p_usw_intr_master[lchip]->p_intr_fatal_end_tbl[type.low_intr + intr_base].p_array[type.lvl4_intr];
            SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    end-intr-table:%s\n", DRV_TABLE_NAME(lchip, SYS_INTR_GET_TBL_ID(tbl_id)));
            if (MEM_TYPE_PER_CORE != TABLE_ENTRY_TYPE(lchip, SYS_INTR_GET_TBL_ID(tbl_id)) || SYS_INTR_GET_TBL_INS_ID(tbl_id))
            {
                SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    [");
                if (MEM_TYPE_PER_CORE != TABLE_ENTRY_TYPE(lchip, SYS_INTR_GET_TBL_ID(tbl_id)))
                {
                    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " oper_bmp:0x%x ", SYS_INTR_GET_TBL_BMP(tbl_id));
                }
                if (SYS_INTR_GET_TBL_INS_ID(tbl_id))
                {
                    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " instance_id:%u ", SYS_INTR_GET_TBL_INS_ID(tbl_id));
                }
                SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "]\n");
            }
        }
    }
    else if (type.intr == SYS_INTR_CHIP_NORMAL)
    {
        if (type.sub_intr >= p_usw_intr_master[lchip]->normal_sub_cnt || p_usw_intr_master[lchip]->p_intr_sub_abnormal[type.intr].p_array[type.sub_intr] == 0)
        {
            return CTC_E_NONE;
        }

        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Normal Interrupr:\n    sub-intr-table:%s\n", DRV_TABLE_NAME(lchip, SYS_INTR_GET_TBL_ID(p_usw_intr_master[lchip]->p_intr_sub_abnormal[type.intr].p_array[type.sub_intr])));

        /*print low intr table*/
        if (type.low_intr >= p_usw_intr_master[lchip]->p_intr_low_normal[type.sub_intr].array_size || p_usw_intr_master[lchip]->p_intr_low_normal[type.sub_intr].p_array[type.low_intr] == 0)
        {
            return CTC_E_NONE;
        }

        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    low-intr-table:%s\n", DRV_TABLE_NAME(lchip, SYS_INTR_GET_TBL_ID(p_usw_intr_master[lchip]->p_intr_low_normal[type.sub_intr].p_array[type.low_intr])));

        if (DRV_FROM_AT(lchip))
        {
            intr_base = p_usw_intr_master[lchip]->normal_sub_base ? p_usw_intr_master[lchip]->normal_sub_base[type.sub_intr] : 0;
            if (type.lvl4_intr >= p_usw_intr_master[lchip]->p_intr_normal_end_tbl[type.low_intr + intr_base].array_size ||
                p_usw_intr_master[lchip]->p_intr_normal_end_tbl[type.low_intr + intr_base].p_array[type.lvl4_intr] == 0)
            {
                tbl_id = p_usw_intr_master[lchip]->p_intr_low_normal[type.sub_intr].p_array[type.low_intr];
                if (MEM_TYPE_PER_CORE != TABLE_ENTRY_TYPE(lchip, SYS_INTR_GET_TBL_ID(tbl_id)) || SYS_INTR_GET_TBL_INS_ID(tbl_id))
                {
                    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    [");
                    if (MEM_TYPE_PER_CORE != TABLE_ENTRY_TYPE(lchip, SYS_INTR_GET_TBL_ID(tbl_id)))
                    {
                        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP," oper_bmp:0x%x ", SYS_INTR_GET_TBL_BMP(tbl_id));
                    }
                    if (SYS_INTR_GET_TBL_INS_ID(tbl_id))
                    {
                        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP," instance_id:%u ", SYS_INTR_GET_TBL_INS_ID(tbl_id));
                    }
                    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"]\n");
                }
                return CTC_E_NONE;
            }
            tbl_id = p_usw_intr_master[lchip]->p_intr_normal_end_tbl[type.low_intr + intr_base].p_array[type.lvl4_intr];
            SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    end-intr-table:%s\n", DRV_TABLE_NAME(lchip, SYS_INTR_GET_TBL_ID(tbl_id)));
            if (MEM_TYPE_PER_CORE != TABLE_ENTRY_TYPE(lchip, SYS_INTR_GET_TBL_ID(tbl_id)) || SYS_INTR_GET_TBL_INS_ID(tbl_id))
            {
                SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    [");
                if (MEM_TYPE_PER_CORE != TABLE_ENTRY_TYPE(lchip, SYS_INTR_GET_TBL_ID(tbl_id)))
                {
                    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " oper_bmp:0x%x ", SYS_INTR_GET_TBL_BMP(tbl_id));
                }
                if (SYS_INTR_GET_TBL_INS_ID(tbl_id))
                {
                    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " instance_id:%u ", SYS_INTR_GET_TBL_INS_ID(tbl_id));
                }
                SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "]\n");
            }
        }
    }
    else
    {
        SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " API or some feature is not supported \n");
        return CTC_E_NOT_SUPPORT;

    }

    return CTC_E_NONE;
}

int32
sys_usw_interrupt_show_status(uint8 lchip)
{
    uint8 i = 0;
    char* mode[5] = {"Pin", "Msi", "Legacy", "Msi-x", "Poll"};

    LCHIP_CHECK(lchip);
    lchip = SYS_PP_BASE(lchip);
    SYS_INTR_INIT_CHECK(lchip);

    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"\n-------------------------Work Mode---------------------\n");

    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-30s:%-6s \n", "Interrupt Mode", mode[p_usw_intr_master[lchip]->intr_mode]);

    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"\n");
    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"-------------------------Group Status---------------------\n");

    for (i = 0; i < SYS_USW_MAX_INTR_GROUP; i++)
    {
        _sys_usw_interrupt_dump_group(lchip, &(p_usw_intr_master[lchip]->group[i]), 0);
    }

    return CTC_E_NONE;
}

#define __INTERRUPT_INTERFACE__
/**
 @brief Set interrupt enable
 Notice: Sdk sys level for enable interrupt should use this interface
*/
int32
sys_usw_interrupt_set_en(uint8 lchip, sys_intr_type_t* p_type, uint32 enable)
{
    SYS_INTR_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_type);
    CTC_MAX_VALUE_CHECK(p_type->intr, SYS_INTR_MAX-1);
    if(p_type->intr == SYS_INTR_CHIP_FATAL|| p_type->intr == SYS_INTR_CHIP_NORMAL)
    {
        return _sys_usw_interrupt_set_en_abnormal(lchip, p_type, enable);
    }
    else if((p_type->intr < SYS_INTR_CPU_SUB_DECODE_0 || p_type->intr > SYS_INTR_CPU_SUB_GPIO) && !(DRV_FROM_AT(lchip) && (p_type->intr == SYS_INTR_DMA)) )/* exclude dma interrupt in at */
    {
        return _sys_usw_interrupt_set_en_func(lchip, p_type, enable);
    }
    else
    {
        return _sys_at_interrupt_set_en_cpu_sub(lchip, p_type, enable);
    }

    return CTC_E_NONE;

}

int32
sys_usw_interrupt_get_en(uint8 lchip, sys_intr_type_t* p_type, uint32* p_enable)
{
    SYS_INTR_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_type);
    CTC_PTR_VALID_CHECK(p_enable);
    CTC_MAX_VALUE_CHECK(p_type->intr, SYS_INTR_MAX-1);
    if(p_type->intr == SYS_INTR_CHIP_FATAL|| p_type->intr == SYS_INTR_CHIP_NORMAL)
    {
        return _sys_usw_interrupt_get_en_abnormal(lchip, p_type, p_enable);
    }
    else
    {
        return _sys_usw_interrupt_get_en_func(lchip, p_type, p_enable);
    }

    return CTC_E_NONE;
}

int32
sys_usw_interrupt_set_group_en(uint8 lchip, uint8 enable)
{
    uint8 i = 0;
    uint32 value = enable ? INTR_INDEX_MASK_RESET : INTR_INDEX_MASK_SET;

    LCHIP_CHECK(lchip);
    SYS_INTR_INIT_CHECK(lchip);
    for(i = 0; i < p_usw_intr_master[lchip]->group_count; i++)
    {
        MCHIP_INTR(lchip)->interrupt_set_sup_op(lchip, p_usw_intr_master[lchip]->group[i].irq_idx, value);
    }

    return CTC_E_NONE;
}

int32
sys_usw_interrupt_get_group_en(uint8 lchip, uint8* enable)
{
    uint8 i = 0;
    uint8 index = 0;
    uint32 value = 0;
    SupIntrGenCtl_m intr_mask;
    uint32 cmd = 0;
    uint8 group_en = 0;
    LCHIP_CHECK(lchip);

    if ((NULL == p_usw_intr_master[lchip]) || p_usw_intr_master[lchip]->init_done == 0)
    {
        *enable = 0;     
        return CTC_E_NONE;
    }
    
    sal_memset(&intr_mask, 0, sizeof(SupIntrGenCtl_m));

    index = DRV_FROM_AT(lchip) ? INTR_INDEX_MASK_SET : 0;
    cmd = DRV_IOR(SupIntrGenCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &intr_mask));

    if (DRV_FROM_AT(lchip))
    {
        value = GetSupIntrGenCtl(V, supIntrGen_f, &intr_mask);
    }
    else
    {
        value = GetSupIntrGenCtl(V, supIntrMaskSet_f, &intr_mask);
    }

    for(i = 0; i < p_usw_intr_master[lchip]->group_count; i++)
    {
        if (!(value & (1<<i)))
        {
            group_en = 1;
            break;
        }
    }

    *enable = group_en;

    return CTC_E_NONE;
}
/**
 @brief Register event callback function
*/
int32
sys_usw_interrupt_register_event_cb(uint8 lchip, ctc_interrupt_event_t event, CTC_INTERRUPT_EVENT_FUNC cb)
{
    LCHIP_CHECK(lchip);
    SYS_INTR_INIT_CHECK(lchip);


    /* check */
    switch (event)
    {
        case CTC_EVENT_PTP_TX_TS_CAPUTRE:
            if(!DRV_FROM_TMM(lchip))
            {
                return CTC_E_NOT_SUPPORT;
            }
            break;
        case CTC_EVENT_ECC_ERROR:
            CTC_ERROR_RETURN(drv_ser_set_cfg(lchip, DRV_SER_CFG_TYPE_ECC_EVENT_CB,cb));
            break;
        default:
            break;
    }

    p_usw_intr_master[lchip]->event_cb[event] = cb;

    return CTC_E_NONE;
}

/**
 @brief get event callback function
*/
int32
sys_usw_interrupt_get_event_cb(uint8 lchip, ctc_interrupt_event_t event, CTC_INTERRUPT_EVENT_FUNC* p_cb)
{
    LCHIP_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_cb);

    SYS_INTR_INIT_CHECK(lchip);

    *p_cb = p_usw_intr_master[lchip]->event_cb[event] ;

    return CTC_E_NONE;
}

/**
@brief get event callback function
*/
int32
sys_usw_interrupt_get_flexe_event_cb(uint8 lchip, ctc_flexe_event_type_t flexe_event, CTC_INTERRUPT_EVENT_FUNC* p_cb)
{
    LCHIP_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_cb);

    SYS_INTR_INIT_CHECK(lchip);

    *p_cb = p_usw_intr_master[lchip]->event_cb[CTC_EVENT_FLEXE_STATUS];

    return CTC_E_NONE;
}

/**
 @brief Other module should call this function to register isr
*/
int32
sys_usw_interrupt_register_isr(uint8 lchip, sys_interrupt_type_t type, CTC_INTERRUPT_FUNC cb)
{
    sys_intr_t* p_intr = NULL;
    lchip = SYS_PP_BASE(lchip);

    LCHIP_CHECK(lchip);
    SYS_INTR_INIT_CHECK(lchip);

    if (DRV_FROM_AT(lchip) && (type == SYS_INTR_FUNC_MAC))
    {
        p_usw_intr_master[lchip]->mac_isr = cb;
    }
    else
    {
        p_intr = &(p_usw_intr_master[lchip]->intr[type]);
        if (p_intr->valid && !p_intr->isr)
        {
            p_intr->isr = cb;
        }
    }
    return CTC_E_NONE;
}

int32
sys_usw_interrupt_register_flexe_isr(uint8 lchip, sys_interrupt_flexe_sub_type_t type, CTC_INTERRUPT_FUNC cb)
{
    LCHIP_CHECK(lchip);
    SYS_INTR_INIT_CHECK(lchip);

    p_usw_intr_master[lchip]->flexe_cb[type] = cb;

    return CTC_E_NONE;
}
int32
sys_usw_interrupt_get_info(uint8 lchip, sys_intr_type_t* p_ctc_type, uint32 intr_bit, uint32* p_intr_tbl, uint8* p_action_type, uint8* p_ecc_or_parity)
{
    drv_ecc_intr_tbl_t tbl_db_info;
    LCHIP_CHECK(lchip);
    SYS_INTR_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_ctc_type);
    CTC_PTR_VALID_CHECK(p_intr_tbl);
    CTC_PTR_VALID_CHECK(p_action_type);
    CTC_PTR_VALID_CHECK(p_ecc_or_parity);

    sal_memset(&tbl_db_info, 0, sizeof(drv_ecc_intr_tbl_t));

    *p_ecc_or_parity = 0;

    if (CTC_INTR_CHIP_NORMAL == p_ctc_type->intr)
    {
        if(p_ctc_type->sub_intr != INVG)
        {
            if(p_ctc_type->low_intr != INVG && p_usw_intr_master[lchip]->p_intr_low_normal[p_ctc_type->sub_intr].array_size)
            {
                *p_intr_tbl = p_usw_intr_master[lchip]->p_intr_low_normal[p_ctc_type->sub_intr].p_array[p_ctc_type->low_intr];
            }
            else
            {
                *p_intr_tbl = p_usw_intr_master[lchip]->p_intr_sub_abnormal[p_ctc_type->intr].p_array[p_ctc_type->sub_intr];
            }
        }
    }
    else if (CTC_INTR_CHIP_FATAL == p_ctc_type->intr)
    {
        if(p_ctc_type->sub_intr != INVG)
        {
            if(p_ctc_type->low_intr != INVG && p_usw_intr_master[lchip]->p_intr_low_fatal[p_ctc_type->sub_intr].array_size)
            {
                *p_intr_tbl = p_usw_intr_master[lchip]->p_intr_low_fatal[p_ctc_type->sub_intr].p_array[p_ctc_type->low_intr];
            }
            else
            {
                *p_intr_tbl = p_usw_intr_master[lchip]->p_intr_sub_abnormal[p_ctc_type->intr].p_array[p_ctc_type->sub_intr];
            }
        }
    }

    if (MaxTblId_t == *p_intr_tbl)
    {
        return CTC_E_NONE;
    }

    tbl_db_info.intr_tblid = *p_intr_tbl;
    tbl_db_info.intr_bit = intr_bit;

    drv_ser_get_cfg(lchip,DRV_SER_CFG_TYPE_ECC_INTERRUPT_INFO, &tbl_db_info);
    *p_action_type = tbl_db_info.action;
    *p_ecc_or_parity = tbl_db_info.tbl_type;

    return CTC_E_NONE;
}

int32
sys_usw_interrupt_proc_ecc_or_parity(uint8 lchip, uint32 intr_tbl, uint32 intr_bit, ctc_intr_type_t intr_type)
{
    drv_ecc_intr_param_t intr_param;

    uint32 bmp[CTC_INTR_STAT_SIZE] = {0};

    sal_memset(&intr_param, 0, sizeof(drv_ecc_intr_param_t));

    CTC_BMP_SET(bmp, intr_bit);
    intr_param.p_bmp = bmp;
    intr_param.intr_tblid = intr_tbl;
    intr_param.total_bit_num = CTC_INTR_STAT_SIZE * CTC_UINT32_BITS;
    intr_param.valid_bit_count = 1;
    intr_param.intr_type = &intr_type;
    CTC_ERROR_RETURN(drv_ser_restore(lchip, &intr_param));
    return CTC_E_NONE;
}

/**
 @brief Initialize interrupt module
*/
int32
sys_usw_interrupt_init(uint8 lchip, void* p_global_cfg)
{
    ctc_intr_global_cfg_t* p_global_cfg_param = (ctc_intr_global_cfg_t*)p_global_cfg;
    static sys_intr_global_cfg_t intr_cfg;
    uint32 group_count = 0;
    uintptr i = 0;
    uint32 j = 0;
    uint32 intr = 0;
    int32 group_id = 0;
    sys_intr_group_t* p_group = NULL;
    sys_intr_t* p_intr = NULL;
    int32 ret = CTC_E_NONE;
    ctc_intr_mapping_t* p_intr_mapping = NULL;
    uint32 intr_idx = 0;
    static ctc_intr_type_t ctc_intr;
    static sys_intr_type_t sys_intr[SYS_USW_MAX_SYS_INTR_TYPE];
    uint8 count = 0;
    uint8 index = 0;
    uint8 irq_idx = 0;
    uint32 offset = 0;

#if (SDB_MEM_MODEL == SDB_MODE)
    return CTC_E_NONE;
#endif

    if ((NULL != p_usw_intr_master[lchip]) && p_usw_intr_master[lchip]->init_done)
    {
        return CTC_E_NONE;
    }
    
    SYS_VCHIP_MASTER_INIT(lchip, p_usw_intr_master, CTC_FEATURE_INTERRUPT);

    p_usw_intr_master[lchip] = mem_malloc(MEM_SYSTEM_MODULE, sizeof(sys_intr_master_t));
    if (NULL == p_usw_intr_master[lchip])
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_usw_intr_master[lchip], 0, sizeof(sys_intr_master_t));

    sal_memset(&intr_cfg, 0, sizeof(intr_cfg));
    sal_memset(&ctc_intr, 0, sizeof(ctc_intr_type_t));

    /* get default interrupt cfg */
    CTC_ERROR_RETURN(sys_usw_interrupt_get_default_global_cfg(lchip, &intr_cfg));
    /* 1. get global configuration */
    if (p_global_cfg_param)
    {
        CTC_PTR_VALID_CHECK(p_global_cfg_param->p_group);
        CTC_PTR_VALID_CHECK(p_global_cfg_param->p_intr);
        group_count = p_global_cfg_param->group_count;

        if (group_count > SYS_USW_MAX_INTR_GROUP)
        {
            return CTC_E_INVALID_PARAM;
        }
        CTC_MAX_VALUE_CHECK(p_global_cfg_param->intr_count, SYS_INTR_MAX);
        CTC_MAX_VALUE_CHECK(p_global_cfg_param->intr_mode, CTC_INTR_MODE_POLL);

        /* mapping user define interrupt group */
        sal_memset(intr_cfg.group, 0, SYS_USW_MAX_INTR_GROUP*sizeof(ctc_intr_group_t));
        sal_memcpy(intr_cfg.group, p_global_cfg_param->p_group, group_count*sizeof(ctc_intr_group_t));

        /* init intr_cfg.intr[].group */
        for (intr_idx = SYS_INTR_CHIP_FATAL; intr_idx < SYS_INTR_MAX; intr_idx++)
        {
            intr_cfg.intr[intr_idx].group = INVG;
        }

        /* mapping user define interrupt */
        for (intr_idx = 0; intr_idx < p_global_cfg_param->intr_count; intr_idx++)
        {
            p_intr_mapping = (ctc_intr_mapping_t*)(p_global_cfg_param->p_intr+intr_idx);
            ctc_intr.intr = p_intr_mapping->intr;
            sal_memset(&sys_intr, 0, sizeof(sys_intr_type_t)*SYS_USW_MAX_SYS_INTR_TYPE);
            ret = sys_usw_interrupt_type_mapping(lchip, &ctc_intr, sys_intr, &count);
            /* interrupt is not used */
            if (ret < 0)
            {
                continue;
            }

            for (index=0; index<count; index++)
            {
                intr_cfg.intr[sys_intr[index].intr].group = p_intr_mapping->group;
            }
        }

        intr_cfg.group_count = group_count;

        /* get interrupt mode */
        intr_cfg.intr_mode = p_global_cfg_param->intr_mode;
    }
    intr_cfg.intr[SYS_INTR_FUNC_STATS_STATUS_ADDR].group = INVG;

    if (DRV_FROM_TMM(lchip))
    {
        intr_cfg.intr[SYS_INTR_FUNC_DP0_MC_MAC0].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_DP0_MC_MAC1].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_DP0_MC_MAC2].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_DP0_MC_MAC3].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_DP0_MC_MAC4].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_DP1_MC_MAC0].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_DP1_MC_MAC1].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_DP1_MC_MAC2].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_DP1_MC_MAC3].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_DP1_MC_MAC4].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_FLEX_DP0].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_FLEX_DP1].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_CPU_MAC].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_SPN_DMA_DROPL].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_SPN_DMA_DROPM].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_SPN_CPU_REPORTL].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_SPN_CPU_REPORTM].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_MISC_MCU_REQ].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_ECPU].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_SCPU].group = 0;
        intr_cfg.intr[SYS_INTR_PCIE_BURST_DONE].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_DP0_MACSEC_RX].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_DP1_MACSEC_RX].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_DP0_MACSEC_TX].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_DP1_MACSEC_TX].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_SVC_POLICING_STATUS_ADDR].group = 0;
        /*from AT*/
        intr_cfg.intr[SYS_INTR_CPU_SUB_ECPU_00].group = 0;
        intr_cfg.intr[SYS_INTR_CPU_SUB_ECPU_01].group = 0;
        intr_cfg.intr[SYS_INTR_CPU_SUB_ECPU_10].group = 0;
        intr_cfg.intr[SYS_INTR_CPU_SUB_ECPU_11].group = 0;
    }

    if (DRV_FROM_AT(lchip))
    {
        intr_cfg.intr[SYS_INTR_FUNC_PTP_SYNC_CODE_IN_RDY].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_PTP_SYNC_PULSE_IN].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_PTP_SYNC_PULSE1].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_PTP_SYNC_CODE_IN_RDY1].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_PTP_TOD_PULSE_IN].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_PTP_TS_CAPTURE_FIFO].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_STATS_STATUS_ADDR].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_STATS_STATUS_ADDR_SLICE_1].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_STATS_STATUS_ADDR_SLICE_2].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_STATS_STATUS_ADDR_SLICE_3].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_IPFIX_USEAGE_OVERFLOW].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_EPE_IPFIX_USEAGE_OVERFLOW].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_MACSEC].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_SVC_POLICING_STATUS_ADDR_1].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_SVC_POLICING_STATUS_ADDR_2].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_SVC_POLICING_STATUS_ADDR_3].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_MAC].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_MISC_EVENT].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_OAM_TWAMP].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_BSR_ERM_MON].group = 0;
        intr_cfg.intr[SYS_INTR_FUNC_BSR_IRM_MON].group = 0;
        for (index = SYS_INTR_FUNC_PTP_TX_TS_FIFO_0_START; index <= SYS_INTR_FUNC_PTP_TX_TS_FIFO_1_END; index++)
        {
            intr_cfg.intr[index].group = 0;
        }
    }
 
    p_usw_intr_master[lchip]->dispatch_fatal = _sys_usw_interrupt_dispatch_fatal;
    p_usw_intr_master[lchip]->dispatch_normal = _sys_usw_interrupt_dispatch_normal;  

    /* 3. create mutex for intr module */
    ret = sal_mutex_create(&(p_usw_intr_master[lchip]->p_intr_mutex));
    if (ret || (!p_usw_intr_master[lchip]->p_intr_mutex))
    {
        mem_free(p_usw_intr_master[lchip]);
        ret = CTC_E_NO_MEMORY;
        return ret;
    }
#if ((SDK_WORK_PLATFORM == 1) || ((0 == SDK_WORK_PLATFORM) && (1 == SDK_WORK_ENV)))  /* simulation */
    ret = sal_mutex_create(&(p_usw_intr_master[lchip]->p_sim_mutex));
    if (ret || (!p_usw_intr_master[lchip]->p_sim_mutex))
    {
        mem_free(p_usw_intr_master[lchip]);
        ret = CTC_E_NO_MEMORY;
        return ret;
    }
#endif
    /* 4. init interrupt & group field of master */
    for (intr = 0; intr < SYS_INTR_MAX; intr++)
    {
        p_usw_intr_master[lchip]->intr[intr].group = INVG;
        p_usw_intr_master[lchip]->intr[intr].intr = INVG;
    }

    for (group_id = 0; group_id < CTC_INTR_MAX_GROUP; group_id++)
    {
        p_usw_intr_master[lchip]->group[group_id].group = INVG;
    }

    /* 5. init interrupt field of master */
    for (i = 0; i < SYS_INTR_MAX; i++)
    {
        if (!sal_strlen(intr_cfg.intr[i].desc))
        {
            continue;
        }
        intr = intr_cfg.intr[i].intr;

        p_intr = &(p_usw_intr_master[lchip]->intr[intr]);
        p_intr->group = intr_cfg.intr[i].group;
        p_intr->intr = intr_cfg.intr[i].intr; /*sys_usw_intr_default[i].intr*/
        p_intr->isr = intr_cfg.intr[i].isr;   /*sys_usw_intr_default[i].isr*/
        sal_strncpy(p_intr->desc, intr_cfg.intr[i].desc, CTC_INTR_DESC_LEN-1);

        if (i == SYS_INTR_PCS_LINK_31_0 || i == SYS_INTR_PCS_LINK_47_32 || i == SYS_INTR_DMA ||
            i == SYS_INTR_FUNC_IPFIX_USEAGE_OVERFLOW || i == SYS_INTR_FUNC_MDIO_CHANGE_0 ||
            i == SYS_INTR_FUNC_MDIO_CHANGE_1 || i == SYS_INTR_FUNC_MDIO_XG_CHANGE_0 ||
            i == SYS_INTR_FUNC_MDIO_XG_CHANGE_1 || i == SYS_INTR_FUNC_DP1_MDIO_XG_CHANGE_0 || 
            i == SYS_INTR_FUNC_DP1_MDIO_XG_CHANGE_1 || i == SYS_INTR_GPIO || i == SYS_INTR_FUNC_CPU_MAC ||
            i == SYS_INTR_FUNC_DP0_MACSEC_RX || i == SYS_INTR_FUNC_DP1_MACSEC_RX || i == SYS_INTR_FUNC_DP0_MACSEC_TX ||
            i == SYS_INTR_FUNC_DP1_MACSEC_TX || i == SYS_INTR_FUNC_PTP_SYNC_CODE_IN_RDY || i == SYS_INTR_FUNC_PTP_TOD_CODE_IN_RDY ||
			i == SYS_INTR_FUNC_MACSEC || i == SYS_INTR_FUNC_BSR_ERM_MON || i == SYS_INTR_FUNC_BSR_IRM_MON ||
            i == SYS_INTR_FUNC_EPE_IPFIX_USEAGE_OVERFLOW || i == SYS_INTR_FUNC_MAC || i == SYS_INTR_FUNC_PTP_SYNC_CODE_IN_RDY1 || i == SYS_INTR_FUNC_OAM_TWAMP ||
            (i >= SYS_INTR_FUNC_DP0_MC_MAC0 && i <= SYS_INTR_FUNC_DP1_MC_MAC3))
        {
            p_intr->is_event = 1;
        }
    }

    for (i = 0; i < intr_cfg.group_count; i++)
    {
        irq_idx = intr_cfg.group[i].group;
        if (irq_idx >= SYS_USW_MAX_INTR_GROUP )
        {
            continue;
        }
        p_group = &(p_usw_intr_master[lchip]->group[i]);
        p_group->group = i;
        p_group->irq = intr_cfg.group[i].irq;
        p_group->prio = intr_cfg.group[i].prio;
        p_group->lchip = lchip;
        p_group->irq_idx = irq_idx;
        sal_strncpy(p_group->desc, intr_cfg.group[i].desc, CTC_INTR_DESC_LEN-1);
        p_group->intr_count = 0;
        p_group->interval = intr_cfg.group[i].interval;

        /* register interrupts to group */
        for (j = 0; j < SYS_INTR_MAX; j++)
        {
            if (p_usw_intr_master[lchip]->intr[j].group == p_group->group)
            {
                p_usw_intr_master[lchip]->intr[j].valid = TRUE;
                p_group->intr_count++;
                if (MCHIP_INTR(lchip)->interrupt_get_intrvec_offset)
                {
                    ret = (MCHIP_INTR(lchip)->interrupt_get_intrvec_offset(lchip, p_usw_intr_master[lchip]->intr[j].intr, &offset));
                    if (ret == CTC_E_NOT_SUPPORT)
                    {
                        continue;
                    }
                }
                CTC_BMP_SET(p_group->intr_bmp, offset);
                if (DRV_FROM_AT(lchip))
                {
                    CTC_BMP_SET(p_group->intr_bmp, offset + SYS_AT_INTR_MAX_PER_CORE);
                }
            }
        }

        p_usw_intr_master[lchip]->group_count++;
    }

    if (MCHIP_INTR(lchip)->interrupt_db_init)
    {
        CTC_ERROR_RETURN(MCHIP_INTR(lchip)->interrupt_db_init(lchip));
    }
    else
    {
        mem_free(p_usw_intr_master[lchip]);
        return CTC_E_NOT_SUPPORT;
    }

    /* 6. init other field of master */
    p_usw_intr_master[lchip]->group_count = intr_cfg.group_count;
    p_usw_intr_master[lchip]->is_default = (p_global_cfg_param) ? FALSE : TRUE;
    p_usw_intr_master[lchip]->intr_count = MCHIP_CAP(SYS_CAP_INTR_MAX_COUNT);/* total intr count(abnormal + func) per chip support */
    p_usw_intr_master[lchip]->intr_mode = intr_cfg.intr_mode;
     
    p_usw_intr_master[lchip]->init_done = (CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING)?2:1;

    CTC_ERROR_RETURN(sys_usw_interrupt_register_isr(lchip, SYS_INTR_CHIP_FATAL, sys_usw_intr_isr_sup_fatal));
    CTC_ERROR_RETURN(sys_usw_interrupt_register_isr(lchip, SYS_INTR_CHIP_NORMAL, sys_usw_intr_isr_sup_normal));
    CTC_ERROR_RETURN(sys_usw_interrupt_register_isr(lchip, SYS_INTR_PCIE_BURST_DONE, sys_usw_intr_isr_pcie));
    drv_ser_register_hw_reset_cb(lchip, DRV_SER_HW_RESET_CB_TYPE_INTERRUPT, sys_usw_interrupt_reset_hw_cb);
#if (FEATURE_MODE == 0) && defined E_UNIT
    if (DRV_FROM_AT(lchip))
    {
        sys_usw_interrupt_register_isr(lchip, SYS_INTR_CPU_SUB_ECPU_00 , sys_usw_eunit_isr_handler);
        sys_usw_interrupt_register_isr(lchip, SYS_INTR_CPU_SUB_ECPU_01 , sys_usw_eunit_isr_handler);
        sys_usw_interrupt_register_isr(lchip, SYS_INTR_CPU_SUB_ECPU_10 , sys_usw_eunit_isr_handler);
        sys_usw_interrupt_register_isr(lchip, SYS_INTR_CPU_SUB_ECPU_11 , sys_usw_eunit_isr_handler);
    }
    else
    {
        sys_usw_interrupt_register_isr(lchip, SYS_INTR_FUNC_ECPU , sys_usw_eunit_isr_handler);
        sys_usw_interrupt_register_isr(lchip, SYS_INTR_FUNC_SCPU , sys_usw_eunit_isr_handler);
        sys_usw_interrupt_register_isr(lchip, SYS_INTR_FUNC_MISC_MCU_REQ , sys_usw_eunit_isr_handler);
    }
#endif
    sys_usw_mchip_set_feature_en(lchip,CTC_FEATURE_INTERRUPT);
    return CTC_E_NONE;

}

int32
sys_usw_interrupt_init_done(uint8 lchip)
{
    int32 ret = CTC_E_NONE;
    sys_intr_group_t* p_group = NULL;
    sys_intr_irq_info_t irq_array[SYS_USW_MAX_INTR_GROUP];
    uint8 irq_idx = 0;
    uint8 irq_count = 0;
    uint16 i = 0;
    uint16 j = 0;
    uint32 status[CTC_INTR_STAT_SIZE];
    uint32 cmd = 0;

    if (SYS_VCHIP_PP_IS_NOT_BASE(lchip))
    {
        return CTC_E_NONE;
    }

    /* get irq info */
    _sys_usw_interrupt_get_irq_info(lchip, &irq_count, irq_array, p_usw_intr_master[lchip]->intr_mode);
    p_usw_intr_master[lchip]->irq_count = irq_count;

    CTC_ERROR_RETURN(_sys_usw_set_interrupt_en(lchip, 0));

    /* clear interrupt log to avoid wake up interrupt dispatch thread 
       when sdk init after deinit */
    sal_memset(status, 0, sizeof(status));
    cmd = DRV_IOW(SupCtlIntrVec_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &status);

    /* 7. init other field of master */
    CTC_ERROR_RETURN(_sys_usw_interrupt_init_reg(lchip));

    /* for msi interrupt, enable msi capbility */
    if (p_usw_intr_master[lchip]->intr_mode == CTC_INTR_MODE_MSI )
    {
        if (g_dal_op.interrupt_set_msi_cap)
        {
            ret = g_dal_op.interrupt_set_msi_cap(SYS_MAP_LDEV(lchip), TRUE, p_usw_intr_master[lchip]->irq_count);
            if (ret)
            {
                SYS_INTETRUPT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "enable msi failed!!\n");
                return ret;
            }
        }

    }
    /* for msi-x interrupt, enable msi-x capbility */
    else if (p_usw_intr_master[lchip]->intr_mode == CTC_INTR_MODE_MSIX)
    {
        if (g_dal_op.interrupt_set_msix_cap)
        {
            ret = g_dal_op.interrupt_set_msix_cap(SYS_MAP_LDEV(lchip), TRUE, p_usw_intr_master[lchip]->irq_count);
            if (ret)
            {
                SYS_INTETRUPT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "enable msix failed!!\n");
                return ret;
             }
         }
    }

    if((((p_usw_intr_master[lchip]->intr_mode > CTC_INTR_MODE_PIN )&& g_dal_op.interrupt_get_irq)
        || (dal_get_soc_active(SYS_MAP_LDEV(lchip)))) && (CTC_INTR_MODE_POLL != p_usw_intr_master[lchip]->intr_mode))
    {
        uint16 irqs[8] = {0};
        uint8  irq_num = 0;

        ret = g_dal_op.interrupt_get_irq(SYS_MAP_LDEV(lchip), p_usw_intr_master[lchip]->intr_mode, irqs, &irq_num);
        if (ret)
        {
            SYS_INTETRUPT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "get irq failed!!\n");
            return ret;
        }

        /* update per group's irq */
        for (i = 0; i < p_usw_intr_master[lchip]->group_count; i++)
        {
            irq_idx = p_usw_intr_master[lchip]->group[i].irq_idx;
            p_usw_intr_master[lchip]->group[i].irq = irqs[irq_idx];
        }

        /*update real irq value*/
        for(i=0; i<irq_count; i++)
        {
            irq_array[i].irq = irqs[i];
        }
    }

    /* init thread per group. but if the irq have only one group, should not init thread */
    for(i = 0; i < irq_count; i++)
    {
        if(irq_array[i].group_count <= 1)
        {
            continue;
        }
        for(j = 0; j < irq_array[i].group_count; j++)
        {
            p_group = &p_usw_intr_master[lchip]->group[(irq_array[i].group[j])];
            if(!p_group->p_sync_sem)
            {
                ret = sal_sem_create(&(p_group->p_sync_sem), 0);
                if (ret < 0)
                {
                    SYS_INTR_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
                    return CTC_E_NOT_INIT;

                }
                CTC_ERROR_RETURN(_sys_usw_interrupt_init_thread(lchip, p_group));
            }
        }
    }

    /* 8. call DAL function to register IRQ */
    if (g_dal_op.interrupt_register  && (CTC_INTR_MODE_POLL != p_usw_intr_master[lchip]->intr_mode))
    {
        for (i = 0; i < irq_count; i++)
        {
            ret = g_dal_op.interrupt_register(irq_array[i].irq, irq_array[i].prio, _sys_usw_interrupt_dispatch, (void*)(uintptr)(irq_array[i].irq_idx));
            if (ret < 0)
            {
                SYS_INTETRUPT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "register interrupt failed!! irq:%d \n", p_group->irq);
                 /*return CTC_E_INTR_REGISTER_FAIL;*/
            }
        }
    }

    if (CTC_INTR_MODE_POLL == p_usw_intr_master[lchip]->intr_mode)
    {
        for (i = 0; i < p_usw_intr_master[lchip]->group_count; i++)
        {
            p_group = &p_usw_intr_master[lchip]->group[i];
            p_group->irq = i;
            ret = _sys_usw_interrupt_init_poll_thread(lchip, p_group);
            if (ret < 0)
            {
                SYS_INTETRUPT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "init poll interrupt failed!! irq:%d \n", p_group->irq);
                return CTC_E_NO_RESOURCE;
            }
        }
    }

    CTC_ERROR_RETURN(_sys_usw_set_interrupt_en(lchip, 1));

    /* clear dma intr for msi */
    if(p_usw_intr_master[lchip]->intr_mode == CTC_INTR_MODE_MSI || p_usw_intr_master[lchip]->intr_mode == CTC_INTR_MODE_MSIX)
    {
        if (DRV_IS_DUET2(lchip))
        {
            Pcie0IntrLogCtl_m pcie_log_ctl;
            uint32 cmd = DRV_IOR(Pcie0IntrLogCtl_t, DRV_ENTRY_FLAG);
            uint32 value_set =0;

            sal_memset(&pcie_log_ctl, 0, sizeof(pcie_log_ctl));
            DRV_IOCTL(lchip, 0, cmd, &pcie_log_ctl);

            if((GetPcie0IntrLogCtl(V, pcie0IntrLogVec_f, &pcie_log_ctl))&&(GetPcie0IntrLogCtl(V, pcie0IntrReqVec_f, &pcie_log_ctl)))
            {
                /* clear dma fun intr */
                cmd = DRV_IOR(DmaCtlIntrFunc_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &value_set);
                cmd = DRV_IOW(DmaCtlIntrFunc_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 1, cmd, &value_set);

                cmd = DRV_IOR(SupIntrFunc_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &value_set);
                cmd = DRV_IOW(SupIntrFunc_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 1, cmd, &value_set);

                /* clear log, trigger intr */
                SetPcie0IntrLogCtl(V, pcie0IntrLogVec_f, &pcie_log_ctl, 0);
                cmd = DRV_IOW(Pcie0IntrLogCtl_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &pcie_log_ctl);
            }
        }
        else
        {
            PcieIntrLogCtl_m pcie_log_ctl;
            Hss12GUnitWrapperInterruptFunc0_m hss_func;
            uint32 cmd = DRV_IOR(PcieIntrLogCtl_t, DRV_ENTRY_FLAG);
            uint32 value_set =0;
            uint32 value_a[CTC_INTR_STAT_SIZE] = {0};

            sal_memset(&pcie_log_ctl, 0, sizeof(pcie_log_ctl));
            DRV_IOCTL(lchip, 0, cmd, &pcie_log_ctl);

            if((GetPcieIntrLogCtl(V, pcieIntrLogVec_f, &pcie_log_ctl))||(GetPcieIntrLogCtl(V, pcieIntrReqVec_f, &pcie_log_ctl)))
            {
                /* clear dma fun intr */
                cmd = DRV_IOR(DmaCtlIntrFunc_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &value_set);
                cmd = DRV_IOW(DmaCtlIntrFunc_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 1, cmd, &value_set);

                cmd = DRV_IOR(Hss12GUnitWrapperInterruptFunc0_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &hss_func);
                cmd = DRV_IOW(Hss12GUnitWrapperInterruptFunc0_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 1, cmd, &hss_func);

                cmd = DRV_IOR(Hss12GUnitWrapperInterruptFunc1_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &hss_func);
                cmd = DRV_IOW(Hss12GUnitWrapperInterruptFunc1_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 1, cmd, &hss_func);

                cmd = DRV_IOR(Hss12GUnitWrapperInterruptFunc2_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &hss_func);
                cmd = DRV_IOW(Hss12GUnitWrapperInterruptFunc2_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 1, cmd, &hss_func);

                cmd = DRV_IOR(RlmHsCtlInterruptFunc_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &value_set);
                cmd = DRV_IOW(RlmHsCtlInterruptFunc_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 1, cmd, &value_set);

                cmd = DRV_IOR(SupIntrFatal_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &value_set);
                cmd = DRV_IOW(SupIntrFatal_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 1, cmd, &value_set);

                cmd = DRV_IOR(SupIntrFunc_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &value_a);
                cmd = DRV_IOW(SupIntrFunc_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &value_a);

                /* clear log, trigger intr */
                SetPcieIntrLogCtl(V, pcieIntrLogVec_f, &pcie_log_ctl, 0);
                SetPcieIntrLogCtl(V, pcieIntrReqVec_f, &pcie_log_ctl, 0);
                cmd = DRV_IOW(PcieIntrLogCtl_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &pcie_log_ctl);

                cmd = DRV_IOR(SupIntrGenCtl_t, SupIntrGenCtl_supIntrValueSet_f);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value_set));
                cmd = DRV_IOW(SupIntrGenCtl_t, SupIntrGenCtl_supIntrValueClr_f);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value_set));
            }
        }
    }

#ifdef _SAL_LINUX_UM
    if (CTC_WB_ENABLE(lchip))
    {
        dal_knet_set_wb_reloading(lchip, 0);
    }
#endif
    return ret;
}

int32
sys_usw_interrupt_free_task(uint8 lchip)
{
    uint32 i = 0;
    sys_intr_group_t* p_group = NULL;

    for (i=0; i< p_usw_intr_master[lchip]->group_count; i++)
    {
        p_group = &(p_usw_intr_master[lchip]->group[i]);
        if (NULL != p_group->p_sync_sem)
        {
            sal_sem_give(p_group->p_sync_sem);
        }
    }
    return CTC_E_NONE;
}

int32
sys_usw_interrupt_deinit(uint8 lchip)
{
    uint32 i = 0;
    sys_intr_group_t* p_group = NULL;
    int32 ret = 0;
    uint8 irq_cnt = 0;
    sys_intr_irq_info_t irq_array[SYS_USW_MAX_INTR_GROUP];

    LCHIP_CHECK(lchip);
    if (NULL == p_usw_intr_master[lchip])
    {
        return CTC_E_NONE;
    }
    if (SYS_VCHIP_PP_IS_NOT_BASE(lchip))
    {
        p_usw_intr_master[lchip] = NULL;
        return CTC_E_NONE;
    }
    p_usw_intr_master[lchip]->init_done = 0;
    /*mask group interrupt*/
    sys_usw_interrupt_set_group_en(lchip, FALSE);

    for (i = 0; i < SYS_INTR_MAX; i++)
    {
        p_usw_intr_master[lchip]->intr[i].isr = NULL;
    }

    for (i = 0; i < CTC_EVENT_MAX; i++)
    {

         p_usw_intr_master[lchip]->event_cb[i] = NULL;
    }

    for (i=0; i< p_usw_intr_master[lchip]->group_count; i++)
    {
        p_group = &(p_usw_intr_master[lchip]->group[i]);
        if (NULL != p_group->p_sync_sem)
        {
            sal_sem_give(p_group->p_sync_sem);
            sal_task_destroy(p_group->p_sync_task);
            sal_sem_destroy(p_group->p_sync_sem);
        }
        if (p_group->p_poll_task)
        {
            sal_task_destroy(p_group->p_poll_task);
        }
    }

    sal_memset(irq_array,0,sizeof(irq_array));
    /* free interrupt */
    if (g_dal_op.interrupt_unregister && (CTC_INTR_MODE_POLL != p_usw_intr_master[lchip]->intr_mode))
    {
        _sys_usw_interrupt_get_irq_info(lchip, &irq_cnt, irq_array, p_usw_intr_master[lchip]->intr_mode);

        for (i = 0; i < irq_cnt; i++)
        {
            ret = g_dal_op.interrupt_unregister(irq_array[i].irq);
            if (ret < 0)
            {
                INTR_UNLOCK;
                return ret;
            }
        }

        /* for msi interrupt */
        if(CTC_INTR_MODE_MSI == p_usw_intr_master[lchip]->intr_mode)
        {
            if (g_dal_op.interrupt_set_msi_cap)
            {
                ret = g_dal_op.interrupt_set_msi_cap(SYS_MAP_LDEV(lchip), FALSE, irq_cnt);
                if (ret)
                {
                    INTR_UNLOCK;
                    SYS_INTETRUPT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "disable msi failed!!\n");
                    return ret;
                }
            }
        }
        else if (CTC_INTR_MODE_MSIX == p_usw_intr_master[lchip]->intr_mode)
        {
            if (g_dal_op.interrupt_set_msix_cap)
            {
                ret = g_dal_op.interrupt_set_msix_cap(SYS_MAP_LDEV(lchip), FALSE, irq_cnt);
                if (ret)
                {
                    INTR_UNLOCK;
                    SYS_INTETRUPT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "disable msix failed!!\n");
                    return ret;
                }
            }
        }
    }
  
    sal_mutex_destroy(p_usw_intr_master[lchip]->p_intr_mutex);
#if ((SDK_WORK_PLATFORM == 1) || ((0 == SDK_WORK_PLATFORM) && (1 == SDK_WORK_ENV)))  /* simulation */
    sal_mutex_destroy(p_usw_intr_master[lchip]->p_sim_mutex);
#endif
    if (p_usw_intr_master[lchip]->p_intr_func)
    {
        mem_free(p_usw_intr_master[lchip]->p_intr_func);
    }
    mem_free(p_usw_intr_master[lchip]);
    p_usw_intr_master[lchip] = NULL;

    return CTC_E_NONE;
}

int32
sys_usw_interrupt_reset_hw_cb(uint8 lchip, void* p_user_data)
{
    int32 ret= CTC_E_NONE;
    LCHIP_CHECK(lchip);
    if ((NULL == p_usw_intr_master[lchip]) || !p_usw_intr_master[lchip]->init_done)
    {
        return CTC_E_NONE;
    }

    INTR_LOCK;
    _sys_usw_interrupt_init_reg(lchip);

    CTC_ERROR_GOTO(_sys_usw_set_interrupt_en(lchip, 1),ret, done);

    /* clear dma intr for msi */
    if((CTC_INTR_MODE_MSI == p_usw_intr_master[lchip]->intr_mode) || (CTC_INTR_MODE_MSIX == p_usw_intr_master[lchip]->intr_mode))
    {
        if (DRV_IS_DUET2(lchip))
        {
            Pcie0IntrLogCtl_m pcie_log_ctl;
            uint32 cmd = DRV_IOR(Pcie0IntrLogCtl_t, DRV_ENTRY_FLAG);
            uint32 value_set =0;

            sal_memset(&pcie_log_ctl, 0, sizeof(pcie_log_ctl));
            DRV_IOCTL(lchip, 0, cmd, &pcie_log_ctl);

            if((GetPcie0IntrLogCtl(V, pcie0IntrLogVec_f, &pcie_log_ctl))&&(GetPcie0IntrLogCtl(V, pcie0IntrReqVec_f, &pcie_log_ctl)))
            {
                /* clear dma fun intr */
                cmd = DRV_IOR(DmaCtlIntrFunc_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &value_set);
                cmd = DRV_IOW(DmaCtlIntrFunc_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 1, cmd, &value_set);

                /* clear log, trigger intr */
                SetPcie0IntrLogCtl(V, pcie0IntrLogVec_f, &pcie_log_ctl, 0);
                cmd = DRV_IOW(Pcie0IntrLogCtl_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &pcie_log_ctl);
            }
        }
        else
        {
            PcieIntrLogCtl_m pcie_log_ctl;
            uint32 cmd = DRV_IOR(PcieIntrLogCtl_t, DRV_ENTRY_FLAG);
            uint32 value_set =0;

            sal_memset(&pcie_log_ctl, 0, sizeof(pcie_log_ctl));
            DRV_IOCTL(lchip, 0, cmd, &pcie_log_ctl);

            if((GetPcieIntrLogCtl(V, pcieIntrLogVec_f, &pcie_log_ctl))&&(GetPcieIntrLogCtl(V, pcieIntrReqVec_f, &pcie_log_ctl)))
            {
                /* clear dma fun intr */
                cmd = DRV_IOR(DmaCtlIntrFunc_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &value_set);
                cmd = DRV_IOW(DmaCtlIntrFunc_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 1, cmd, &value_set);

                /* clear log, trigger intr */
                SetPcieIntrLogCtl(V, pcieIntrLogVec_f, &pcie_log_ctl, 0);
                SetPcieIntrLogCtl(V, pcieIntrReqVec_f, &pcie_log_ctl, 0);
                cmd = DRV_IOW(PcieIntrLogCtl_t, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, 0, cmd, &pcie_log_ctl);
            }
        }
    }

done:
    INTR_UNLOCK;
    return ret;
}
